PDA

View Full Version : آموزش: آموزش هایی در رابطه با C#‎



Sajjad.Aghapour
چهارشنبه 07 اسفند 1387, 20:50 عصر
Singleton یکی از الگوهای معمولی است که بسیاری از برنامه نویسان ازآن به وفور استفاده می کنند.هدف از این الگو این است که اطمینان حاصل شود که از یک کلاس فقط یک نمونه وجود داشته باشد.این نوع الگو می تواند در موارد زیادی مفید باشد از جمله:


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


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


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


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


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


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


public class SingletonPattern
{
private SingletonPattern() { }

private static SingletonPattern instance = new SingletonPattern();
public static SingletonPattern GetInstance
{
get
{
return instance;
}
}

}


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


SingletonPattern s = SingletonPattern.GetInstance;


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


SingletonPattern s1 = SingletonPattern.GetInstance;
SingletonPattern s2 = SingletonPattern.GetInstance;


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


public class Program
{
public static void Main(string[] args)
{
SingletonPattern s1 = SingletonPattern.GetInstance;
SingletonPattern s2 = SingletonPattern.GetInstance;

if (s1 == s2)
Console.WriteLine("Refer to the same object");

Console.ReadLine();
}

}


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


public class SingletonPattern
{
private SingletonPattern() { }

private static SingletonPattern instance = new SingletonPattern();
public static SingletonPattern GetInstance
{
get
{
lock (typeof(SingletonPattern))
{
if (instance != null)
instance = new SingletonPattern();
}
return instance;
}
}

}


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


public class SingletonPattern
{
private SingletonPattern() { }

class SingletonCreator
{
private static SingletonCreator() { }
internal static readonly SingletonPattern instance = new SingletonPattern();
}

public static SingletonPattern GetInstance
{
get
{
return SingletonCreator.instance;
}
}
}

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

Sajjad.Aghapour
سه شنبه 28 مهر 1388, 10:51 صبح
Extension Methods

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


public class Program
{
public static void Main(string[] args)
{
string s = "120";
Console.WriteLine(ExtensionMethods.ToInt32(s));
Console.ReadLine();
}
}
public static class ExtensionMethods
{
public static int ToInt32(string s)
{
if (string.IsNullOrEmpty(s))
throw new ArgumentException();
return int.Parse(s);
}
}


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


public class Program
{
public static void Main(string[] args)
{
string s = "120";
Console.WriteLine(s.ToInt32());
Console.ReadLine();
}
}
public static class ExtensionMethods
{
public static int ToInt32(this string s)
{
if (string.IsNullOrEmpty(s))
throw new ArgumentException();
return int.Parse(s);
}
}


در اینجا نتیجه با مثال قبل یکسان خواهد بود ولی تفاوتی که با آن دارد این است که فراخوانی آن ساده تر و کدهای نوشته شده به این حالت قابل درک و جامع تر خواهند بود.
اما اجازه دهید آن را از لحاظ MSIL(Microsoft Intermediate Language) بررسی کنیم.


http://sajjadaghapour.files.wordpress.com/2010/03/il1.jpg


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


http://sajjadaghapour.files.wordpress.com/2010/03/il2.jpg


همانطور که مشاهده می کنید در فراخوانی این متد در تابع Main این متد با صفت ExtensionMethods مشخص شده است.بنابراین کامپایلر خواهد فهمید که این متد در حقیقت یک Extension Method است.
اما تفاوت دیگری که اینگونه متد ها دارند این است که شما قادر خواهید بود در Intellisense آنها را مشاهده کنید.این متدها همانطور که در شکل می بینید به این صورت مشاهده خواهند شد:
• یک فلش رو به پایین
• دربرداشتن رشته (extension) در tooltipی که متد را معرفی میکند


http://sajjadaghapour.files.wordpress.com/2010/03/ex3.jpg


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

اطلاعات بیشتر
http://barnamenevis.biz/forum/showthread.php?t=100281
http://www.barnamenevis.biz/forum/showpost.php?p=463602&postcount=33

Sajjad.Aghapour
چهارشنبه 26 اسفند 1388, 01:06 صبح
اکثر برنامه نویسان وقتی میخواهند دو رشته را به هم بچسبانند از عملگر + استفاده میکنندو به این ترتیب دو رشته باهمدیگر ترکیب خواهند شد.برای concatenate دو روش خواهیم داشت.یکی استفاده از همین عملگر + که برای الحاق دو رشته از نوع string مورد استفاده قرار میگیره و یکی هم استفاده از StringBuilder.
تفاوت استفاده از این دو روش فقط در Performance هست و هر دو روش نتیجه یکسانی رو به ما خواهد داد.
اما چه اتفاقی میافته وقتی که ما از روش زیر برای concatenate استفاده میکنیم.

str1 += str2;

در این مورد استفاده با وجود اینکه ما دو نوع داریم ولی 3 نمونه در حافظه خواهیم داشت.اما دلیل :
در .Net آبجکت های string تغییرناپذیر هستن.یعنی وقتی به وجود میان مقدار اونها قابل تغییر نخواهد بود.به همین دلیل هست که وقتی مقدار str1 با str2 الحاق میشه در حقیقت str1 قبلی دور ریخته میشه و یک نمونه (instance) جدید از اون ساخته میشه که مقدار حاصل از concatenate را خواهد داشت.یعنی با این تعاریف 3 نمونه str1 قبلی، str1 جدید و یک نمونه هم از str2 که قبلا وجود داشته و تغییری نکرده است.
حالا تصور کنید ما بخواهیم این عمل رو چندین بار با یک نمونه انجام بدیم که این کار باعث به وجود آمدن instance های اضافی در حافظه خواهد شد.
حالا ببینیم StringBuilder چگونه کار میکنه؟!

StringBuilder sb = new StringBuilder();
sb.Append(str2);

StringBuilder برخلاف string تغییرپذیر است.به همین دلیل شما فقط یک نمونه از این کلاس خواهید داشت و وقتی یک رشته جدید رو به اون می چسبونید نمونه دیگری از اون ایجاد نخواهد شد و رشته جدید به نمونه موجود از StringBuilder اضافه خواهد شد.

طبیعتا استفاده از StringBuilder به صرفه تر و سریعتر خواهد بود.

موفق باشید

Sajjad.Aghapour
جمعه 28 اسفند 1388, 12:24 عصر
Func<> یک delegate است که یک متد را اجرا میکند.این delegate چند پارامتر را به عنوان ورودی گرفته (می تواند پارامتری ورودی نداشته باشد) و یکی از پارامترها را که به صورت TResult مشخص می شود را به عنوان خروجی برمیگرداند.

یکی از Prototype های این delegate به صورت زیر میباشد:

public delegate TResult Func<T1, T2, TResult>(
T1 arg1,
T2 arg2
)


که T1 و T2 پارامترهای ورودی و TResult نتیجه اجرای تابع خواهد بود.شما وقتی از این delegate استفاده میکنید دیگر نیازی به تعریف صریح یک delegate و یک متد نخواهید داشت.با این تعاریف شما با به کار بردن Func یک delegate و یک Encapsulated Method خواهید داشت.در اینجا نحوه کاربردهای متعددی از این delegate را توضیح خواهم داد.

تعریف زیر تعریف یک delegate ساده است که یک متد(به اینگونه متدها که به صورت Explicit تعریف می شوند Named Method گفته میشود که نقطه مقابل Anonymous Method می باشند) را اجرا خواهد کرد.

public delegate string[] SplitString(string param);

public static void Main(string[] args)
{
SplitString split = Split;
string str = "my name is sajjad";
foreach (string s in split(str))
{
Console.WriteLine(s + Environment.NewLine);
}
}

private static string[] Split(string param)
{
return param.Split(' ');
}


حال اگر خواسته باشیم با استفاده از Func این کار را انجام دهیم و البته به صورتی که یک Named Method را اجرا کند به صورت زیر خواهد شد:

public static void Main(string[] args)
{
Func<string, string[]> split = Split;
string str = "my name is sajjad";
foreach (string s in split(str))
{
Console.WriteLine(s + Environment.NewLine);
}
}

private static string[] Split(string param)
{
return param.Split(' ');
}


نحوه کارکرد کاملا مشخص است و همانند مثال قبل می باشد.پارامترهای ورودی و خروجی تعریف شده در Func با امضای (پارامترهای ورودی و خروجی) تابع Split همخوانی دارد، لدا خواهیم توانست این متد را توسط این delegate اجرا کنیم.

مثالی که در بالا مشاهده کردید مثالی از نحوه کارکرد Func بود که البته یک Named Method را اجرا میکرد.اما چطور یک Anonymous Method را با آن اجرا کنیم؟ اگر تعریف Anonymous Method را میدانید پس خواهید توانست این کار را انجام دهید.به مثال زیر دقت کنید:

public static void Main(string[] args)
{
Func<string, string[]> split = delegate(string s)
{
return s.Split(' ');
};
string str = "my name is sajjad";
foreach (string s in split(str))
{
Console.WriteLine(s + Environment.NewLine);
}
}

به همین راحتی...

شما از طریق Lambda Expression هم خواهید توانست این کار را هرچه بهتر انجام دهید.

public static void Main(string[] args)
{
Func<string, string[]> split = (s) =>
{
return s.Split(' ');
};
string str = "my name is sajjad";
foreach (string s in split(str))
{
Console.WriteLine(s + Environment.NewLine);
}
}

اگر در مورد Lambda Expression میدانید توجه داشته باشید که در اینجا نیازی به تعریف نوع متغیر نمی باشد.کامپایلر نوع ‘s’ را بر اساس نوع تعریف شده در Func تشخیص میدهد و همانگونه با آن رفتار میکند.

اما مزیت Lambda Expression را در مثال زیر با همان کارکرد بالا می توانید متوجه شوید:

public static void Main(string[] args)
{
Func<string, string[]> split = (s => s.Split(' '));
string str = "my name is sajjad";
foreach (string s in split(str))
{
Console.WriteLine(s + Environment.NewLine);
}
}

می بینید که به منظور ساده سازی عبارت ما به چه نحو عمل کردیم.

Sajjad.Aghapour
جمعه 28 اسفند 1388, 12:42 عصر
در پست قبل در مورد 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");
}

Sajjad.Aghapour
جمعه 06 فروردین 1389, 02:57 صبح
یکی ازمسائلی که در وراثت بسیاری از برنامه نویسان را گیج میکند سازنده ها و مخرب ها هستند.در این مقاله کوتاه به بررسی و توضیح این مسئله می پردازیم:


سازنده ها به ترتیب از پدر به فرزند شروع به اجرا می کنند. یعنی ابتدا پدر ساخته میشه و بعد فرزند(طبیعتا تا پدری نباشد فرزندی هم نخواهد بود)
مخرب ها برعکس خواهد بود.یعنی از فرزند به پدر اجرا خواهند شد.ابتدا مخرب در فرزند اجرا و بعد در پدر اجرا خواهد شد(فکر میکنید چرا به این شکل است؟ جواب: از همون قانونی که در نکته قبل ضمیمه کردم استفاده کنید ببینید چرا بدین شکل اجرا می شوند)
نحوه اجرای سازنده های 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 = b2 = null;
GC.Collect();

Console.ReadLine();
}
}



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


http://sajjadaghapour.files.wordpress.com/2010/03/constructors.gif



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


public class Program
{
public static void Main(string[] args)
{
A.TestMethod();

Console.ReadLine();
}
}

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
}

}




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


http://sajjadaghapour.files.wordpress.com/2010/03/static-constructor.gif


اما چرا سازنده های static ؟
جواب (و همچنین اطلاعات بیشتر) در msdn (http://msdn.microsoft.com/en-us/library/k9x6w0hc%28VS.80%29.aspx)


موفق باشید/

Sajjad.Aghapour
پنج شنبه 13 خرداد 1389, 02:02 صبح
بی مقدمه...

بهترین تعداد آرگومانهای یک تابع صفر(niladic) است.بعد از آن یک(monadic) و بعد از آن دو(dyadic).تعداد سه آرگومان(triadic) تا جائیکه ممکن است نباید استفاده شود.اما بیش از سه آرگومان(polyadic) نیاز به اصلاح دارد و تحت هر شرایطی نباید استفاده شود.
اما گاهی اوقات ممکن است توابع و آبجکت هایی وجود داشته باشند که سه یا بیشتر از سه آرگومان را می پذیرند و معمولا هم توسط یک سازنده مقدار اولیه خواهند گرفت.ممکن است بعضی از آرگومان های آنها نیاز نباشد که در این صورت شما می توانید با دادن مقدار پیش فرض یا توسط overload کردن در موقع لزوم به آنها مقدار بدهید.اما با این حال نباید از اصل موضوع دور بشویم و بی خیال به کدنویسی خود ادامه بدهیم.
مفهوم Fluent در مهندسی نرم افزار به این دلیل ابداع شد که بتوان واسط کاربری را تهیه کرد که از لحاظ خوانایی بیشترین کیفیت را داشته باشد(Fluent Interface).چیزی که در .Net 3.0 به بعد به وفور به خصوص در LINQ دیده می شود.
فرض کنید کلاسی دارید که اطلاعات شخصی یک نفر را به طور کامل به شما میدهد(مثال رو زیاد پیچیده نمی کنم).به طور معمول از این طریق استفاده می شود(البته بدون تعریف Property)


public class Person
{
string fName;
string lName;
string nName;

public Person(string firstName, string nickName, string lastName)
{
this.fName = firstName;
this.nName = nickName;
this.lName = lastName;
}

public string FullName()
{
StringBuilder sb = new StringBuilder();
sb.Append((fName == string.Empty) ? "" : fName);
sb.Append((lName == string.Empty) ? "" : lName);
sb.Append((nName == string.Empty) ? "" : " (" + nName + ")");

return sb.ToString();
}
}


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


Person p = new Person("Sajjad", "sajjadlove", "Aghapour");
MessageBox.Show(p.FullName());


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


public class PersonBuilder
{
string fName;
string lName;
string nName;

public PersonBuilder WithFirstName(string firstName)
{
this.fName = firstName;
return this;
}

public PersonBuilder WithLastName(string lastName)
{
this.lName = lastName;
return this;
}

public PersonBuilder WithNickName(string nickName)
{
this.nName = nickName;
return this;
}

public string FullName()
{
StringBuilder sb = new StringBuilder();
sb.Append((fName == string.Empty) ? "" : fName);
sb.Append((lName == string.Empty) ? "" : lName);
sb.Append((nName == string.Empty) ? "" : " (" + nName + ")");

return sb.ToString();
}
}


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


PersonBuilder pb = new PersonBuilder();
string name = pb.WithFirstName("Sajjad")
.WithNickName("sajjadlove")
.WithLastName("Aghapour")
.FullName();

MessageBox.Show(name);



تا به حال به این نحوه پیاده در LINQ زیاد برخورده اید زیرا این نحوه پیاده سازی در ایجاد Query و اجرای آنها بسیار مناسب و کاربردی است.
البته شما میتوانید به عنوان یک developer قدرت خود را گسترش و به طراحی Fluent Interface هایی که میتواند مفید واقع شوند بپردازید.

hamedsabzian
پنج شنبه 13 خرداد 1389, 05:22 صبح
اما بیش از سه آرگومان(polyadic) نیاز به اصلاح دارد و تحت هر شرایطی نباید استفاده شود.
دلیل این همه تاکید، فقط افزایش خواناییه؟ یا مشکلات دیگه ای ممکنه به وجود بیاد؟

sia_2007
پنج شنبه 13 خرداد 1389, 07:34 صبح
البته در مثال خاصی که زده اید؛ استفاده از Object Initializer راحت تر و خواناتر است.
دوست عزیز ؛ hamedsabzian؛ معمولا تعداد پارامترهای بالا مشمول قواعد Refactoring میشوند؛ و باید در قالب یک شی ؛ Encapsulate شوند و سپس ارسال شوند.

Sajjad.Aghapour
پنج شنبه 13 خرداد 1389, 13:01 عصر
البته در مثال خاصی که زده اید؛ استفاده از Object Initializer راحت تر و خواناتر است.

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



دلیل این همه تاکید، فقط افزایش خواناییه؟ یا مشکلات دیگه ای ممکنه به وجود بیاد؟

بر اساس مستنداتی (http://en.wikipedia.org/wiki/Fluent_interface)که وجود دارد و معنای Fluent (روان و سلیس) ، با این قابلیت شما خواهید توانست قابلیت خوانایی کدتون رو بالا ببرید.این مفهوم در کنار مفاهیمی چون Reusabilty , Extensibility و در کل مفهوم Refactoring (http://en.wikipedia.org/wiki/Refactoring)معنای بیشتری پیدا خواهد کرد.

برای پی بردن به اهمیت این موضوع و دلایل کافی برای دانستن آن این تاپیک (http://barnamenevis.org/forum/showthread.php?p=1001010) رو دنبال کنید

emdadgar2
چهارشنبه 19 خرداد 1389, 07:54 صبح
اما به نظر شما این تو در تو سازی کد و فراخوانی آنها، در انجام پروژه های واقعی تر (و البته پیچیده و سنگین تر) پروسس و زمان بیشتر مصرف نخواهد کرد؟

Sajjad.Aghapour
چهارشنبه 19 خرداد 1389, 12:17 عصر
اما به نظر شما این تو در تو سازی کد و فراخوانی آنها، در انجام پروژه های واقعی تر (و البته پیچیده و سنگین تر) پروسس و زمان بیشتر مصرف نخواهد کرد؟


بگذارید یک مثال از خود NET. بزنم تا بیشتر با کاربرد اون آشنا بشید:

string[] names = { "ali", "ahmad", "gholi", "jafar", "saeid", "saman" };

var lastFilteredName = names.Select(name => name)
.Where(name => name.StartsWith("a"))
.Last();

خروجی:


ahmad

به نحوه پیاده سازی توابع Select, Where دقت کنید، بدین صورت پیاده سازی شده اند:

//Select
public static IEnumerable<TResult> Select<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> selector);

//Where
public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate);


همانطور که مشاهده میکنید این مورد یکی از موارد کاربرد در LINQ میباشد که برای ایجاد یک Query به شما کمک خواهد کرد.البته در اینجا Extension Method هم نقش بزرگی رو ایفا میکنه که آموزش اون هم در همین تاپیک وجود داره....
این یک تکنیک هست برای Readability بیشتر در کدهای شما...

اگر منظور شما غیر از این هست بگید تا بیشتر توضیح بدم....

Sajjad.Aghapour
دوشنبه 21 تیر 1389, 13:53 عصر
سلام دوستان
یکی از کمبودهایی که در #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);


موفق باشید/

Sajjad.Aghapour
شنبه 13 شهریور 1389, 22:58 عصر
سلام دوستان

چندوقتی هست که جهت اعتبار سنجی سوالاتی پرسیده میشه.لینکی که برای شما خواهم گذاشت لیستی از Extension Method هایی هستش که برای اعتبار سنجی رشته ها به شما کمک خواهد کرد.شما میتوانید این متدها رو گسترش بدید و در پروژه های خودتون(چه Web App و چه Win App) استفاده کنید.

http://www.codegain.com/codesnippets/csharp/miscellaneous/the-collection-of-extension-methods-in-C-Sharp.aspx

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


// Check if the string variable is convertible to inteager or not
string num = "12";
bool valid = num.IsNumber();

// Check if the string is a valid Email address or not
string email = "test@test.com";
bool valid = email.IsEmail();

// And so on
//