تمام سوالات سوالات بدون پاسخ سوال بپرسید

در رابطه با پارامتر های اختیاری(optional) در C# 4 من متوجه شده ام که چنانچه پارامتری را بصورت اختیاری (optional) در واسط تعریف کنیم، نیازی به تعریف آن پارامتر در سایر کلاس های پیاده سازی دیگر نمی باشد.

public interface MyInterface  
{  
    void TestMethod(bool flag=false);  
}

public class MyClass : MyInterface
{
    public void TestMethod(bool flag)
    {
        Console.WriteLine(flag);
    }
}

بنابراین:

var obj = new MyClass();  
obj.TestMethod(); // compiler error

var obj2 = new MyClass() as MyInterface;
obj2.TestMethod(); // prints false

آیا کسی می داند که به چه دلیل این پارامترها برای کار به این شکل طراحی شده اند؟ با این فرض که امکان تعریف مقادیر از پیش تعریف شده در واسط(interface) برنامه بسیار مفید است، اما گمان نمی کنم نیازی باشد که در واسط این کار صورت بگیرد( این کار مربوط به تصمیم گیری های مرتبط با پیاده سازی می باشد). از طرفی دیگر اگر این امکان وجود نداشته باشد، شما نمی توانید Class Concrete و واسط ها را به جای یکدیگر استفاده نمایید. البته این مسئله هنگامی که مقدار پیش فرض در بخش پیاده سازی تعریف گردد مشکلی پیش نخواهد آورد، اما چنانچه بخواهید از یک کلاس بعنوان واسط استفاده نمایید( بعنوان مثال استفاده از برخی IOC framework ها بمنظور وارد کردن یک concrete class)، هیچ راهی برای داشتن یک مقدار پیش فرض وجود ندارد ، بهمین دلیل همیشه باید توسط فراخواننده (caller) این مقدار اولیه ایجاد گردد.
منبع:
stackoverflow

من پاسخ را نمی دانم اما خیلی دوست دارم جواب را بدانم.

(30 اوت '11, 03:27) hamedkh ♦

آیا به این دلیل که آنها اختیاری (optional) می باشند؟ کنجکاو هستم علت را بفهمم.

(30 اوت '11, 03:28) hamedkh ♦

اگر شما می گویید که این پارامتر ها در contract اختیاری هستند، چرا به خود برنامه نویس اجازه نمی دهید که آن را ایجاد کند؟

(30 اوت '11, 03:28) hamedkh ♦

توضیحات بیشتر را می توانید در لینک زیر بیابید:
http://geekswithblogs.net/BlackRabbitCoder/archive/2010/06/17/c-optional-parameters---pros-and-pitfalls.aspx

(30 اوت '11, 03:29) hamedkh ♦
2 پاسخ

چنین فرض می کنیم که شما واسطی مشابه با آنچه توصیف کردید دارید و صدها کلاس نیز وجود دارد که آن را پیاده سازی می کنند. حال شما تصمیم می گیرید که پارمتری را از یکی از متدهای واسط برنامه، اختیاری (optional) تعریف نمایید. آیا پیشنهاد شما این است که کامپایلر باید برنامه نویس را مجبور سازد که تمامی پیاده سازی های موجود از آن متد را جستجو کند و پارامتر را در آنها نیز اختیاری کند؟
من که چنین فکر نمی کنم. حال چنین درنظر بگیرید که برنامه نویس به source code برای پیاده سازی دسترسی نداشته باشد:


// in metadata:
public class B 
{ 
    public void TestMethod(bool b) {}
}

// in source code
interface MyInterface 
{ 
    public void TestMethod(bool b = false); 
}
class D : B, MyInterface {}
// Legal because D's base class has a public method 
// that implements the interface method

آیا نویسنده D باید گوشی تلفن را بردارد و با نویسنده B تماس بگیرد و از او بخواهد تا نسخه جدیدی از B را که در متد آن یک پارامتر اختیاری تعریف شده است را برای او بفرستد؟
حال اگر دو فرد با نویسنده B تماس بگیرند و یکی از انها بخواهد مقدار پیش فرض true باشد و دیگری بخواهد false باشد، چه باید کرد؟ اگر نویسنده B نخواهد این کار را انجام دهد چه؟
شاید در این مورد بهتر است این گونه عمل نمود:

class D : B, MyInterface 
{
    public new void TestMethod(bool b = false)
    {
        base.TestMethod(b);
    }
}

ویژگی پیشنهاد شده سختی های زیادی را برای برنامه نویس بوجود خواهد آورد در حالی که هیچ سودی در جهت افزایش قدرت نمایش ندارد. پس سود اصلی این ویژگی چیست که هزینه تحمیلی از آن را برای کاربران قابل قبول می نماید.

غیر منطقی است که در کلاس های پیاده سازی محدودیتی برای استفاده از یک مقدار پیش فرض یکسان در واسط وجود داشته باشد .

(30 اوت '11, 03:32) hamedkh ♦

فکر می کنم که تنها راهی که ممکن می سازد متد های واسط ما آرگومان هایی اختیاری داشته باشند که در تمامی پیاده سازی ها یکسان باشد، این است که متد های اضافی (extension methods) در واسط داشته باشند که سربار را کنترل نمایند.

(30 اوت '11, 03:33) hamedkh ♦

یک پارامتر اختیاری (optional) به یک Attribute مربوط می باشد. Attribute به کامپایلر اعلام می کند که مقدار پیش فرض را در زمان فراخوانی (call-site) به پارامتر نسبت دهد.
در هنگام کامپایل شدن کد های C# به IL، فراخوانی obj2.TestMethod(); با obj2.TestMethod(false); جایگزین می گردد.( این کار در زمان JIT-time انجام نمی گیرد).
بنابراین یک روش این است که فراخواننده همیشه مقادیر اولیه را فراهم کند.این کار همچنین تاثیراتی را بر روی binary virsioning در پی دارد: چنانچه شما مقدار پیش فرض را تغییر دهید بدون آنکه مجددا کد را کامپایل نمایید، در هنگام فراخوانی کد مقادیر قبلی آن مورد استفاده قرار می گیرد.

از طرفی دیگر اگر این امکان وجود نداشته باشد شما نمی توانید کلاس های concrete و واسط ها را به جای یکدیگر استفاده نمایید.
چنانچه متد های واسط بصورت صریح explicit تعریف شوند،شما نمی توانید این کار را انجام دهید

منظور شما از " اگر متد های واسط صریح تعریف شده باشند؟" چیست؟ آیا می توانید مثالی بزنید؟

(30 اوت '11, 03:36) hamedkh ♦

متوجه شدم....ممنون از اینکه آن را به من نشان دادید.

(30 اوت '11, 03:37) hamedkh ♦
toggle preview



آموزش زبان برنامه نویسی C#
آموزش jquery
آموزش برنامه نویسی
آموزش طراحی وبسایت
آموزش مدیریت وبسایت
آموزش جاوا Java
آموزش پایتون Python
آموزش سی شارپ C#‎
آموزش HTML و CSS
آموزش JavaScript جاوااسکریپت
آموزش jQuery جی کوئری
آموزش ساخت ربات تلگرام
آموزش برنامه‌نویسی PHP
آموزش برنامه‌نویسی اندروید
● آموزش‌های رایگان

سوالات مرتبط

راهنمای استفاده از ویرایشگر
  • *ایتالیک*‌ یا __ایتالیک__
  • **ضخیم** یا __ضخیم__
  • آدرس:[متن](http://url.com/ "عنوان")
  • عکس?![alt متن](/path/img.jpg "عنوان")
  • لیست عددی: 1. Foo 2. Bar
  • برای رفتن به خط بعد، هر جا مایلید که خط جدید شروع شود دو کاراکتر فاصله (space) قرار دهید
  • تگ‌های ساده HTML هم پشتیبانی می‌شوند

تگها:
این سوال را دنبال کنیدتوسط ایمیل: ایمیل شما (باید معتبر باشد, هرگز به دیگران نمایش داده نمیشود):

هنگامی که شما به سیستم وارد شوید،قادر خواهید بود برای بروز رسانی ها مشترک شوید.


توسط RSS:

پاسخها

پاسخها و نظرها