بایگانی

Posts Tagged ‘#C’

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);
Advertisements
دسته‌ها: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 برچسب‌ها: , ,

کدنویسی 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 برچسب‌ها: , ,

نحوه کار کردن با Action delegate

در پست قبل در مورد Func<> delegate و نحوه کار کردن با آن صحبت کردم.اما شاید از خودتان بپرسید اگر بخواهیم از این امکان طوری استفاده کنیم که خروجی نداشته باشیم(خروجی ما void) باشد باید چه کار کنیم.جواب استفاده از Action<> delegate است.

توضیحاتی که در مورد این delegate وجود دارد همان توضیحاتی است که در مورد <>Func داده شده است و تنها تفاوت آنها در خروجی آنها می باشد.البته اگر متد شما پارامتر ورودی ندارد باید از Action به جای <>Action استفاده کنید.

مثال با استفاده از delegate و Named Method :

public delegate void Writer(string path, string content);public static void Main(string[] args)

{

Writer writer = WriteToFile;

writer(@»c:\test.txt», «my name is sajjad»);

}

private static void WriteToFile(string path, string content)

{

StreamWriter sw= null;

try

{

sw= new StreamWriter(path);

sw.Write(content);

}

finally

{

if (sw!= null)

sw.Close();

}

}

مثال با استفاده از Action و Named Method:

public static void Main(string[] args){

Action<string, string> writer = WriteToFile;

writer(@»c:\test.txt», «my name is sajjad»);

}

private static void WriteToFile(string path, string content)

{

StreamWriter sw = null;

try

{

sw = new StreamWriter(path);

sw.Write(content);

}

finally

{

if (sw!= null)

sw.Close();

}

}

مثال با استفاده از Action<> و Anonymous Method :

public static void Main(string[] args){

Action<string, string> writer = delegate(string path, string content)

{

StreamWriter sw = null;

try

{

sw = new StreamWriter(path);

sw.Write(content);

}

finally

{

if (sw != null)

sw.Close();

}

};

writer(@»c:\test.txt», «my name is sajjad»);

}

مثال با استفاده از Action<> و Lambda Expression :

public static void Main(string[] args){

Action<string, string> writer = (path, content) =>

{

StreamWriter sw = null;

try

{

sw = new StreamWriter(path);

sw.Write(content);

}

finally

{

if (sw != null)

sw.Close();

}

};

writer(@»c:\test.txt», «my name is sajjad»);

}

موفق باشید/


Vote on iDevCenter

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