بایگانی

Posts Tagged ‘.Net’

Optional Parameters and Named Parameters in .NET 4.0

یکی از کمبودهایی که در C#‎ احساس میشد استفاده از Optional Parameters در تعریف یک تابع بود که معمولا با استفاده از Overloading قابل پیاده سازی بود.اما همانطور که میدانید، در NET 4.0. این امکان وجود دارد که شما بتوانید در تعریف پارمتهای یک تابع Optional Parameters را هم داشته باشید.

private void Foo(int x = 10)
{
   //Do Something
}

اما هدف اصلی معرفی Named Arguments هست که به نظر من بهترین نحوه استفاده از آن همراه با استفاده از Optional Parameters هست.
[بدون شرح]
فرض کنید یک تابع دارید با یک Required Parameter و دو Optional Parameter:

private void Foo(int x, int y = 20, int z = 30)
{
   //Do Something
}

برای اینکه این تابع را فراخوانی کنید، سه Prototype در اختیار شما قرار خواهد گرفت:
مثال *

Foo(10); // x = 10
Foo (10, 40); // x = 10, y = 40
Foo(10, 40, 50); // x = 10, y = 40, z = 50

ملاحظه میکنید که برای مقدار دهی z باید از حالت سوم استفاده بشه.شما با Named Arguments قادر خواهید بود متغیر خود رو برای مقداردهی مشخص کنید.در حالت کلی میتوانید به این صورت بنویسید(فراخوانی به صورت دو صورت زیر یک نتیجه مشابه دارد):

<

Foo(x: 10, y: 50, z: 20);
Foo(y: 50, z: 20, x: 10);

خوب با این وجود، شما برای مقدار دهی به z لزومی ندارد که از حالت سوم در مثال قبل(مثال *) استفاده کنید.یعنی شما به این صورت کار خود را انجام خواهید داد:

Foo(10, z: 50); // like: Foo(10, 20, 50);
دسته‌ها:C#.Net برچسب‌ها: , , , ,

داشتن بیش از یک مقدار بازگشتی از یک تابع

ژوئیه 11, 2010 ۱ دیدگاه

چندوقتی هست که Nutshell رو میخوام مطالعه کنم، اما به علل گوناگون قادر به این کار نیستم.داشتم فصل دو این کتاب رو جهت Persistance نگاه می انداختم، به نکته ای که چندوقت در جواب دوستم بهش دادم(در اصرار عدم استفاده از Property) برخوردم.گفتم بگذارم دوستان هم استفاده کنند.راستش این روش زیاد به کار من هم نیومده ولی خوب در بعضی جاها میشه به طور موثر از اون استفاده کرد:

The out modifier is most commonly used to get multiple return values back from a method. For example:
class Test
    {
        static void Split(string name, out string firstNames,
        out string lastName)
        {
            int i = name.LastIndexOf(' ');
            firstNames = name.Substring(0, i);
            lastName = name.Substring(i + 1);
        }
        static void Main()
        {
            string a, b;
            Split("Stevie Ray Vaughn", out a, out b);
            Console.WriteLine(a); // Stevie Ray
            Console.WriteLine(b); // Vaughn
        }
    }
دسته‌ها:C#.Net برچسب‌ها: , ,

تفاوت File Version و Assembly Version

در حالت کلی File Version مربوط به فایل ها یا DLL هایی است که شما میتوانید در برنامه خود استفاده کنید.و Assembly Version مربوط به برنامه خود شما خواهد بود که در آن تعیین میشود چه نوع فایل هایی میتوانند در برنامه استفاده شوند.

اگر بخواهم یک مثال بزنم:
مجموعه Office رو در نظر بگیرید.فرض کنید با Word 2007 دارید کار میکنید.در این ورژن از نرم افزار شما قادر خواهید بود با File Version های doc و docx کار کنید و آنها را درون نرم افزار load کنید.در حقیقت این به معنی وجود یک Assembly Version به همراه دو File Version است.Word 2003 و 2007 کاملا متفاوت از هم رفتار میکنن در حالیکه فرمت doc در آنها یکی خواهد بود(البته این یک نگاه کلی بدون در نظر گرفتن جزئیات است).

این مورد را هم میتوانیم در تفاوت آنها در نظر بگیریم که چهارچوب و سیستم عاملی که شما از آن استفاده میکنید فقط درگیر Assembly Version خواهند بود و مسئولیتی در قبال File Version نخواهند داشت.
شما هربار که برنامه رو Build میکنید در واقع بر حسب کدهایی که در برنامه تغییر داده اید Assembly Version رو افزایش خواهی داد که این کار توسط خود VS یا نرم افزارهای Versioning قابل انجام خواهد بود.اما در مورد File Version این ترفند کاملا به خود شما و سیاست نرم افزار شما بستگی دارد.یعنی برخلاف File Version ، Assembly Version توسط .Net Runtime و دیگر نرم افزارهای Versioning استفاده می شود….

این از تفاوت.اما اینکه کی از File Version و کی از Assembly Version استفاده کنیم نیز جای بحث دارد.برای مثال:

اینکه شما می خواهید یکی از این دو را افزایش دهید بستگی به یک سوال دارد:
شما برای چه منظور برنامه را ویرایش میکنید؟

و جواب آن به شما کمک خواهد کرد تا بفهمید کدام را افزایش دهید:

  1. آیا میخواهید Interface برنامه رو تغییر بدید؟ در این مورد Assembly Version را افزایش دهید.اما چرا؟ این به این دلیل است که شما Interfaceی به برنامه اضافه کرده اید که در ورژن های قبلی کاربران از آن استفاده نمی کرده اند.
  2. قابلیت جدیدی رو به نرم افزار اضافه کنید؟ در این مورد نیز Assembly Version را باید افزایش داد.چون در این مورد شما می خواهید نرم افزار قبل همچنان پابرجا باشد و اگر کاربران خواستند از قابلیت های اضافه شده استفاده کنند.
  3. باگی رو میخواهید اصلاح کنید؟ در این صورت File Version را باید افزایش دهید.چرا؟ در این مورد اینکه به تمام کاربران بگوئید که به ورژن جدید switch کنند کمی دردسر خواهد بود.مفهوم Package ها نیز در اینجا مطرح می شود.در واقع Package ها به نرم افزار شما این قابلیت را خواهند داد تا از پذیرفتن چیزهایی که قبلا به عنوان باگ در نرم افزار پذیرفته می شده است پرهیز کنند.(البته در اینجا شاید بتوان گفت که در ورژن بعدی نرم افزار این باگ نیز برطرف می شود.ولی این از اصول طراحی نرم افزار است ولی در حال حاضر به هیچ عنوان نباید به خاطر یک باگ یک Assembly Version تازه داشته باشیم)
دسته‌ها:C#.Net برچسب‌ها: , , ,

کدنویسی Fluent در Net.

آوریل 16, 2010 ۱ دیدگاه

در این مقاله قصد دارم به معرفی تکنیکی بپردازم که به منظور خواناتر کردن کدنویسی به کار گرفته می شود.بهترین تعداد آرگومانهای یک تابع صفر(niladic) است.بعد از آن یک(monadic) و بعد از آن دو(dyadic).تعداد سه آرگومان(triadic) تا جائیکه ممکن است نباید استفاده شود.اما بیش از سه آرگومان(polyadic) نیاز به اصلاح دارد و تحت هر شرایطی نباید استفاده شود.

اما گاهی اوقات ممکن است توابع و آبجکت هایی وجود داشته باشند که سه یا بیشتر از سه آرگومان را می پذیرند و معمولا هم توسط یک سازنده مقدار اولیه خواهند گرفت.ممکن است بعضی از آرگومان های آنها نیاز نباشد که در این صورت شما می توانید با دادن مقدار پیش فرض یا توسط overload کردن در موقع لزوم به آنها مقدار بدهید.اما با این حال نباید از اصل موضوع دور بشویم و بی خیال به کدنویسی خود ادامه بدهیم.

مفهوم Fluent در مهندسی نرم افزار به این دلیل ابداع شد که بتوان واسط کاربری را تهیه کرد که از لحاظ خوانایی بیشترین کیفیت را داشته باشد(Fluent Interface).چیزی که در .Net 3.0 به بعد به وفور به خصوص در LINQ دیده می شود.

فرض کنید کلاسی دارید که اطلاعات شخصی یک نفر را به طور کامل به شما میدهد(مثال رو زیاد پیچیده نمی کنم).به طور معمول از این طریق استفاده می شود(البته بدون تعریف Property)

    1 public class Person

    2 {

    3     string fName;

    4     string lName;

    5     string nName;

    6 

    7     public Person(string firstName,

    8         string nickName, string lastName)

    9     {

   10         this.fName = firstName;

   11         this.nName = nickName;

   12         this.lName = lastName;

   13     }

   14 

   15     public string FullName()

   16     {

   17         StringBuilder sb = new StringBuilder();

   18         sb.Append((fName == string.Empty) ? "" : fName);

   19         sb.Append((lName == string.Empty) ? "" : lName);

   20         sb.Append((nName == string.Empty)

   21             ? "" : " (" + nName + ")");

   22 

   23         return sb.ToString();

   24     }

   25 }

و نحوه استفاده نیز به شکل زیر خواهد بود:

    1 Person p = new Person("Sajjad", "sajjadlove", "Aghapour");

    2 MessageBox.Show(p.FullName());

شاید به خودتان بگوئید که ظاهرا مشکلی در این نحوه کدنویسی وجود ندارد، اما اگر پارامترهای شما بیش از سه باشد به راحتی در ایجاد object دچار سردرگمی خواهید شد.راه حل چیست؟به مثال زیر دقت کنید:

اگر کلاس Person را به صورت زیر پیاده سازی کنیم:

    1 public class PersonBuilder

    2 {

    3     string fName;

    4     string lName;

    5     string nName;

    6 

    7     public PersonBuilder WithFirstName(string firstName)

    8     {

    9         this.fName = firstName;

   10         return this;

   11     }

   12 

   13     public PersonBuilder WithLastName(string lastName)

   14     {

   15         this.lName = lastName;

   16         return this;

   17     }

   18 

   19     public PersonBuilder WithNickName(string nickName)

   20     {

   21         this.nName = nickName;

   22         return this;

   23     }

   24 

   25     public string FullName()

   26     {

   27         StringBuilder sb = new StringBuilder();

   28         sb.Append((fName == string.Empty) ? "" : fName);

   29         sb.Append((lName == string.Empty) ? "" : lName);

   30         sb.Append((nName == string.Empty)

   31             ? "" : " (" + nName + ")");

   32 

   33         return sb.ToString();

   34     }

   35 }

نحوه استفاده به شکل زیر خواهد بود:

    1 PersonBuilder pb = new PersonBuilder();

    2 string name = pb.WithFirstName("Sajjad")

    3     .WithNickName("sajjadlove")

    4     .WithLastName("Aghapour")

    5     .FullName();

    6 

    7 MessageBox.Show(name);

تا به حال به این نحوه پیاده سازی در LINQ زیاد برخورده اید زیرا این نحوه پیاده سازی در ایجاد Query و اجرای آنها بسیار مناسب و کاربردی است.

دسته‌ها:C#.Net برچسب‌ها: , , ,

Singleton Pattern

مارس 27, 2010 4 دیدگاه

Singleton یکی از الگوهای معمولی است که بسیاری از برنامه نویسان ازآن به وفور استفاده می کنند.هدف از این الگو این است که اطمینان حاصل شود که از یک کلاس فقط یک نمونه وجود داشته باشد.این نوع الگو می تواند در موارد زیادی مفید باشد از جمله:

  • وقتی منابع بار زیادی داشته باشند مانند Linq Data Context
  • برنامه های چند نخی که ممکن است در نخ های دیگر سعی به ایجاد نمونه دیگری ازکلاس مورد نظر باشد
  • Global Resources
  • و موارد زیادی از این قبیل

در یک کلاس Singleton دو چیز مورد نیاز خواهد بود:

  1. یک متغیر private static که نمونه مورد نظر از کلاس را نگه می دارد
  2. یک متد static که این نمونه را برمی گرداند

البته این موارد به موارد زیر جهت بهبود الگو تغییر پیدا میکنند:

  1. یک سازنده private که البته اگر این سازنده static باشد بهتر است
  2. یک متغیر private static که نمونه مورد نظر از کلاس را نگه می دارد
  3. یک پروپرتی public static که این نمونه را برمی گرداند

یک نمونه که با توجه به تعاریف موجود می توان نشان داد کد زیر است:

1 public class SingletonPattern

2 {

3 private SingletonPattern() { }

4

5 private static SingletonPattern instance = new SingletonPattern();

6 public static SingletonPattern GetInstance

7 {

8 get

9 {

10 return instance;

11 }

12 }

13 }

و نحوه فراخوانی آن هم به شکل زیر خواهد بود:

1 SingletonPattern s = SingletonPattern.GetInstance;

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

1 SingletonPattern s1 = SingletonPattern.GetInstance;

2 SingletonPattern s2 = SingletonPattern.GetInstance;

اگرچه این کد دو نمونه متفاوت را ایجاد میکند، اما هردو نمونه به یک شی ارجاع داده می شوند.کد زیر این مسئله را نشان میدهد:

1 public class Program

2 {

3 public static void Main(string[] args)

4 {

5 SingletonPattern s1 = SingletonPattern.GetInstance;

6 SingletonPattern s2 = SingletonPattern.GetInstance;

7

8 if (s1 == s2)

9 Console.WriteLine(«Refer to the same object»);

10

11 Console.ReadLine();

12 }

13 }

اما الگویی که تا الان ما طراحی کردیم thread-safe نخواهد بود.یعنی ممکن است نخ دیگری همزمان اقدام به ایجاد کلاس کند.یک راه این است که ایجاد کلاس را lock کنید.به کد زیر توجه کنید:

1 public class SingletonPattern

2 {

3 private SingletonPattern() { }

4

5 private static SingletonPattern instance = new SingletonPattern();

6 public static SingletonPattern GetInstance

7 {

8 get

9 {

10 lock (typeof(SingletonPattern))

11 {

12 if (instance != null)

13 instance = new SingletonPattern();

14 }

15 return instance;

16 }

17 }

18

19 }

اما مشکلی که این روش دارد این است که احتمال وقوع بن بست را افزایش خواهد داد.بهترین راه برای این کار Lazy Instantiation خواهد بود.در این روش نمونه گیری از کلاس Singleton در یک کلاس تودرتو (Nested Class) انجام میشود.

1 public class SingletonPattern

2 {

3 private SingletonPattern() { }

4

5 class SingletonCreator

6 {

7 private static SingletonCreator() { }

8 internal static readonly SingletonPattern instance =

9 new SingletonPattern();

10 }

11

12 public static SingletonPattern GetInstance

13 {

14 get

15 {

16 return SingletonCreator.instance;

17 }

18 }

19

20 }

نکته ای که می توان به آن اشاره کرد این است که در Perfoemance این روش نسبت به روش قبل کارایی بیشتری دارد.

Vote on iDevCenter

دسته‌ها:C#.Net برچسب‌ها: , , ,

سازنده ها، سازنده های static و مخرب ها در وراثت

یکی ازمسائلی که در وراثت بسیاری از برنامه نویسان را گیج میکند سازنده ها و مخرب ها هستند.در این مقاله کوتاه به بررسی و توضیح این مسئله می پردازیم:

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

اجازه بدید با یک مثال این مسئله رو بهتر متوجه می شویم.

public class A

{

public A()

{

Console.WriteLine(«A public constructor»);

}

static A()

{

Console.WriteLine(«A Static Constructor»);

}

~A()

{

Console.WriteLine(«A Destructor»);

}

}

public class B : A

{

public B()

{

Console.WriteLine(«B public constructor»);

}

static B()

{

Console.WriteLine(«B Static Constructor»);

}

~B()

{

Console.WriteLine(«B Destructor»);

}

}

در تابع اصلی آنها را به این صورت به کار خواهیم برد:

public class Program

{

public static void Main(string[] args)

{

B b1 = new B();

B b2 = new B();

b1 = b1 = null;

GC.Collect();

Console.ReadLine();

}

}

از null کردن نمونه ها و GC.Collect() برای نشان دادن اجرای مخرب کلاس ها استفاده کردیم.خروجی به شکل زیر خواهد بود:

مسئله ای که در اینجا می توان بیشتر توضیح داد و شاید دلیل اصلی ایجاد این پست، سازنده های static هستند.این سازنده ها به محض دادن هر ارجاعی به کلاس ساخته خواهند شد.این مسئله را می توانید در مثال زیر بهتر متوجه شوید:

public class A

{

public A()

{

Console.WriteLine(«A public constructor»);

}

static A()

{

Console.WriteLine(«A Static Constructor»);

}

~A()

{

Console.WriteLine(«A Destructor»);

}

public static void TestMethod()

{

//Some code here

}

}

public class Program

{

public static void Main(string[] args)

{

A.TestMethod();

Console.ReadLine();

}

}

با توجه به تعریفی که کردیم با فراخوانی ()A.TestMethod سازنده static اجرا خواهد شد لذا خروجی به شکل زیر خواهد بود:

اما چرا سازنده های static ؟

جواب (و همچنین اطلاعات بیشتر) در msdn

Vote on iDevCenter

دسته‌ها:C#.Net برچسب‌ها: ,

Extension Methods

این نوع متدها که یکی از ویژگی هایی است که در C# 3.0 ارائه شده است به شما اجازه خواهند داد که شما به یک نوع موجود، متدهایی را اضافه کنید بدون اینکه از یک نوع مشتق شده استفاده کنید، یا اینکه یک کامپایل مجدد داشته باشید و یا اینکه آن نوع را به طرز جدیدی اصلاح کنید.این مفهوم به شما اجازه خواهد داد تا متدهایی را به کلاس هایی اضافه کنید که ممکن است حتی سورس کد انها را نداشته باشید.
شما هر نوعی را که گسترش دهید، با داشتن یک نمونه (Instance) از آن می توانید این متد را فراخوانی کنید.یک مزیت  Extension Methods وقتی است که شما یک کلاس sealed داشته باشید و قصد گسترش آن را داشته باشید.

در ابتدا اجازه دهید متدهای static را بررسی کنیم.

اگرچه این کد به خوبی کار میکند اما همانطور که مشاهده میکنید نوشتن آن کمی مشکل خواهد بود.

برای اینکه این کد را ساده کنیم می توانیم از Extension Method استفاده کنید. و اما مشخصات اینگونه متدها:

  • این نوع متدها در کلاس های static پایه ریزی می شوند و با استفاده از نمونه های نوع مربوطه فراخوانی می شود.
  • خود متد static است.
  • اولین پارامتر این متد(پارامتر instance یا نمونه)، نوعی است که قصد گسترش آن را داریم و با کلمه کلیدی this تعریف می شود.
  • پارامتر instance نمی تواند از نوع اشاره گر باشد.
  • پارامتر instance نمی تواند با استفاده از ref, out و … امضا شود.در نتیجه این پارامتر نباید با مرجع فراخونی شود.
  • این متد باید public, internal و private باشد.بهتر است که public باشد.
  • این متدهای فقط در محدوده namespaceی هستند که در آن تعریف شده اند.

در اینجا نتیجه با مثال قبل یکسان خواهد بود ولی تفاوتی که با آن دارد این است که فراخوانی آن ساده تر و کدهای نوشته شده به این حالت قابل درک و جامع تر خواهند بود.

اما اجازه دهید آن را از لحاظ MSIL(Microsoft Intermediate Language) بررسی کنیم.

همانطور که در شکل بالا مشاهده می کنید کدی که ما نوشتیم در IL به فراخوانی یک متد ساده static ترجمه شده است.و این به این معنی است که Extension Method چیزی زیادتر از یک متد static نیست. اما کامپایلر چگونه میفهمد که این متد یه Extension Method است؟

همانطور که مشاهده می کنید در فراخوانی این متد در تابع Main این متد با صفت ExtensionMethods مشخص شده است.بنابراین کامپایلر خواهد فهمید که این متد در حقیقت یک Extension Method است.

اما تفاوت دیگری که اینگونه متد ها دارند این است که شما قادر خواهید بود در Intellisense آنها را مشاهده کنید.این متدها همانطور که در شکل می بینید به این صورت مشاهده خواهند شد:

  • یک فلش رو به پایین
  • دربرداشتن رشته (extension) در tooltipی که متد را معرفی میکند

نکته آخر هم درباره استفاده از این متدها در LINQ است که اگر با LINQ آشنایی داشته باشد میدانید که از Extension Methods در LINQ زیاد استفاده می شود.


Vote on iDevCenter

دسته‌ها:C#.Net برچسب‌ها: , ,