مقدمه :
خوب دوستان من به یک مشکلی داشتم سرچ میکردم که چشم خورد به یک سوال در stackoverflow که برام جالب بود گفتم سوال جواب بنویسم. از این به بعد هم قصد دارم اگر به همچنین سوالاتی بر خوردم با تگ stackoverflow بنویسم.
در زمان نوشتن این مطلب ، مدت زمان 10 سال و 5 ماه از این پرسش و پاسخ گذشته است !
عنوان اصلی و منبع C#: Returning 'this' for method nesting?
من یک کلاس دارم که مجبور هستم یک یا دو متد آن را بارها بعد از یکدیگر صدا بزم. در حال حاضر متدها void برمیگردانند. داشتم فکر می کردم،آیا بهتر است return را برگردانم، به طوری که متدها را می توان nested کرد؟ (البته از سی شارپ 7 میشود متد های تو در تو یا به عبارت دیگر متد های محلی یا همون Local Function نوشت ) یا خیلی بد است؟ یا اگر بد باشد ، بهتر است اگر یک شیء جدید از همان نوع را برگرداند؟به عنوان نمونه ، من سه نسخه از کلاس Adder"افزودنی" ایجاد کرده ام:
// Regular عادی class Adder { public Adder() { Number = 0; } public int Number { get; private set; } public void Add(int i) { Number += i; } public void Remove(int i) { Number -= i; } } // Returning this برگرداندن کلمه کیلیدی class Adder { public Adder() { Number = 0; } public int Number { get; private set; } public Adder Add(int i) { Number += i; return this; } public Adder Remove(int i) { Number -= i; return this; } } // Returning new برگرداندن شی جدید class Adder { public Adder() : this(0) { } private Adder(int i) { Number = i; } public int Number { get; private set; } public Adder Add(int i) { return new Adder(Number + i); } public Adder Remove(int i) { return new Adder(Number - i); } }
اولین (Regular عادی) مورد از این طریق قابل استفاده است:
var a = new Adder(); a.Add(4); a.Remove(1); a.Add(7); a.Remove(3);
از دو متد دیگر(برگرداند this و برگرداندن شی جدید) می توان به این روش استفاده کرد:
var a = new Adder() .Add(4) .Remove(1) .Add(7) .Remove(3);
تنها تفاوت (بین متدهایی که شی جدید و کلمه کلیدی this برمیگردانند) جایی است که a در مورد اول new Adder() است در حالی که در مورد دوم نتیجه متد آخر است.
در مورد اولین متد چیزی که به سرعت پیدا کردم اینکه بارها و بارها نوشتن آزار دهنده است.بنابراین می خواهم از یکی از دو نسخه آخر استفاده کنم.متد سوم (برگرداندن شی جدید) مانند بسیاری از متدهای دیگر مثل بسیاری از متدهای String و extensions method هایی مثل IEnumerable کار می کند.من حدس می زنم استفاده از متد سوم جنبه مثبت اش این است که می توانید کارهایی مانند:
var a = new Adder(); var b = a.Add(5);
انجام بدهیم و که یکی را که 0 است و دیگری که 5 است(منظورش اینکه توسط متد سوم "ایجاد شی جدید" میتوانیم مقادیر را داخل متغیر هم بریزیم).اما در عین حال ، آیا ساختن اشیاء جدید همزمان کمی هزینه بر نیست؟و چه زمانی اولین شی خواهد مُرد(فکر کنم منظورش اینکه چه زمانی نابود و از حافظه پاک میشه!)؟هنگامی که متد اول به نوعی برگردد؟ یا چی ؟
به هر حال ، من آن متدی را که this را برگرداند دوست دارم و فکر کنم از آن استفاده خواهم کرد ، اما من بسیار کنجکاو هستم که بدانم دیگران درباره این مورد چه فکر می کنند.و کدامشان بهترین عمل محسوب می شود(best practice هست).
(جواب خودم :استفاده از از الگوی Chain of Responsibility و یا ساخت Fluent API .)
جواب انتخاب شده: سبک "return this" گاهی اوقات یک fluent interface خوانده می شود و یک روال معمول (common practice) است.
هر دو return this و return new نمونه هایی با کاربردهای مختلف:
jQuery $('#eleId').show()
کد بالا this را بر می گرداند زیرا در غیر این صورت یک کپی eleId ایجاد می کند.
لینک/Linq در کد زیر
myCollection.Where(x=>x.IsValid)
یک new object برمی گرداند زیرا در غیر این صورت می توانست myCollection را تغییر دهد ،که تغییر ناپذیر است(immutable است)
نکته کلیدی این است که return this باعث تغییر شی اصلی میشود ولی return new باعث میشود شی اصلی تغییری نکند برای مثلا در jQuery شی اصلی تغییر میکند چون return this است. این رفتار مورد انتظار ست - در غیر این صورت اساساً عناصر UI را کلون کنید(اگر نمی خواهید شی اصلی را تغییر دهید).همچنین در Linq کالکشن اصلی تغییری نمیکند که همین رفتار انتظار می رود - هر تابع زنجیر شده یک فیلتر یا تغییر شکل است ، و شی اصلی غالبا immutable است.
کدام الگوی مناسب تر برای آنچه انجام می دهید ،است؟
توضیحی در مورد Immutable
An immutable type, in the context of C#, is a type of object whose data cannot be changed after its creation. An immutable type sets the property or state of the object as read only because it cannot be modified after it is assigned during initialization. ... Immutable types provides higher security than mutable types.
منبع
یعنی وقتی شی رو ساختی دیگر نمی توانی مقدارش را تغییر دهید مثلا string از نوع immutable هست بدین معنا که اگر متغییر زیر را تعریف کردید
string Name = "arman"
مقداری در حافظه (heap) اشغال میکند .اگر مقدار آن را مانند زیر تغییر دهید :
Name = "Arman"
مقدار جدید حافظه جدیدی اشغال می کند.


من نه مترجم هستم و نه کلاس زبان رفتم ، از طرفی هم شنیدم می گویند نباید دخل و تصرفی در ترجمه ایجاد کنید! برای همین توصیه من این هست که همیشه منبع اصلی رو ببینید. به امید روزی که زبانم قوی کنم ! :)
cafe (╯°□°)╯︵ ┻━┻ (کافه رو ریختم به هم)