مفهوم Automatic Properties :
همانطور که میدونید ، دات نت برای بدست آوردن و اعمال مقادیر به فیلدهای خصوصی (private) از properties استفاده میکنه، تا اینکه بخواد از متدهای تجاری Getxxx() و Setxxx() استفاده کنه، به مثال زیر نگاه کنید که فیلدی از نوع string رو encapsulate کرده :


کد:
// A Car type using standard property
// syntax.
class Car
{
private string carName = string.Empty;
public int PetName
{
get { return carName; }
set { carName = value; }
}
}
در حالی که تعریف propertyهای سی شارپ زیاد مشکل نیست، شما با این موافق هستید که به propertyهاتون مقداری نسبت بدید یا مقدارش رو بلافاصله در همونجا برگردونید، اما اگه چندتا فیلد داشته باشید و بخواهید به این شکل براشون کد نویسی کنید، یه مقدار خسته کننده خواهد بود، فرض کنید شما نیاز به 15 فیلد خصوصی دارید، علاوه بر این شما بایستی 15 تا property رو تعریف کنید که نسبتا کار زیاد و دشواری خواهد بود.
برای ساده کردن پروسه ی تعریف فیلدهای encapsulate شده، C#‎ 2008 یک syntax جدیدی رو به نام automatic properties معرفی کرده. همانطور که از نامش پیداست، این syntax جدید، تعریف فیلدهای private و propertyهای مربوطه رو راحت و سریع کرده، برای روشن شدن موضوع، مثال مربوط به کلاس Car (مثال قبلی) رو میشه به این صورت پیاده کرد :


کد:
class Car
{
// Automatic property syntax.
public string PetName { get; set; }
}
در نگاه اول، automatic properties شبیه abstract properties به نظر میاد که بایستی در کلاسهای فرزند override بشه، اونم با وجود دو آیتم get و set که اجرا نشدند. به هر حال این، اون نیست، اگه شما میخواهید یک abstract property در کلاس Car بالا تعریف کنید، بایستی از کلمه ی کلیدی abstract به شکل زیر استفاده کنید :


کد:
abstract class Car
{
// Abstract property in an abstract base class.
public abstract string PetName { get; set; }
}
وقتی میخواهید automatic properties رو تعریف کنید، بسادگی، توصیف کننده های دسترسی رو مشخص میکنید، نوعش رو هم مشخص میکنید، نامش رو هم مشخص میکنید، و یک محدوده ی get / set خالی. در زمان کامپایل، کلاس شما به صورت اتوماتیک، فیلدهای خصوصی و کدهای مربوطه رو با منطق مناسب با get و set تولید خواهد کرد.
توجه : نام فیلدهای privateای که به صورت اتوماتیک توسط سی شارپ تولید میشه رو نمیشه در داخل کدی که شما نوشتی دید، تنها راه دیدن اونا، استفاده از ابزارهایی مانند ildasm.exe است.

برخلاف propertyهای معمولی سی شارپ، شما نمیتونید automatic properties رو به صورت read-only یا write-only بسازید، در حالی که شما فکر میکنید که فقط با حذف get; یا set; این کار امکان پذیره، مانند زیر :


کد:
// Read-only property? Error!
public int MyReadOnlyProp { get; }
// Write only property? Error!
public int MyWriteOnlyProp { set; }
این کار، خطای کامپایلر رو نتیجه خواهد داد. پس وقتی شما automatic properties رو تعریف میکنید، بایستی هر دو مورد رو تعریف کنید (read,write).

تعامل با Automatic Properties :
چون کامپایلر فیلدهای خصوصی متناظر رو در زمان کامپیال تولید خواهد کرد، کلاسی که automatic properties رو تعریف کرده، همیشه به دستور نحوی property برای گرفتن و نسبت دادن مقادیر نیاز خواهد داشت. توجه به این نکته خیلی مهمه چون بسیاری از برنامه نویسان مستقیما از همون فیلدهای خصوصی که درتعریف کلاسشون ساختن استفاده میکنن، در صورتی که در اینجا چنین چیزی امکان پذیر نیست. برای مثال، اگر کلاس Car متد ToString() رو override کنه، شما برای اجرای این متد به نام property نیاز خواهد داشت :


کد:
class Car
{
public string PetName { get; set; }
public override string ToString()
{
// No access to the private member in the defining
// class. Must use properties!
return string.Format("PetName = {0}", PetName);
}
}
وقتی شما از آبجکتی استفاده میکنید که automatc properties رو تعریف کرده، شما از طریق syntax مورد انتظار برای گرفتن یا نسبت دادن مقادیر به/از آن استفاده میکنید:


کد:
static void Main(string[] args)
{
Console.WriteLine("***** Fun with Automatic Properties *****");
Car c = new Car();
c.PetName = "Frank";
Console.WriteLine("Your car is named {0}? That's odd...",
c.PetName);
Console.ReadLine();
}
محدودیت دسترسی روی Automatic Properties :
به یاد بیاورید که propertyهای معمولی دات نت میتونن با توصیف کننده های دسترسی جداگانه ای برای منطق get و set ساخته بشن، برای مثال، شما مجاز هستید که یک محدوده ی get رو به صورت public و یک محدوده ی set رو به صورت محافظت شده یا protected تعریف کنید :


کد:
// Anyone can get the PetName value, but
// only the defining type and the children can set it.
public int PetName
{
get { return carName; }
protected set { carName = value; }
}
به صورت مشابه بالا، شما میتونید همچنین این موضوع رو برای automatic properties هم بکار ببرید، با syntax زیر :
کد:
کد:
public string PetName { get; protected set; }
خب با این تغییری که الان دادیم، در متد main مثال قبل، یک خطای زمان کامپایل رو تولید خواهد کرد وقتی که میخواهید مقداری رو به PetName اعمال کنید :


کد:
static void Main(string[] args)
{
...
// Error! Setting the PetName is only possible
// from within the Car type or by a child type!
c.PetName = "Frank";
// Getting the value is still OK.
Console.WriteLine("Your car is named {0}? That's odd...",
c.PetName);
Console.ReadLine();
}
نکاتی راجع به Automatic Properties و مقادیر پیشفرض :
وقتی از automatic properties برای encapsulate کردن داده های Boolean یا numerical استفاده میکنید، قادرید که از نوع properties ای که بصورت اتوماتیک تولید میشه فورا در داخل کدتون استفاده کنید، به فیلد مخفی تولید شده (private field) یک مقدار ایمن نسبت میده که میتونه مستقیما استفاده بشه. بهرحال مواظب باشید وقتی از syntax مربوط به automatic property برای انواع ارجاعی استفاده میکنید چون مقدار فیلد مخفی private اون به صورت پیشفرض، null قرار داده میشه :


کد:
class Garage
{
// The hidden int backing field is set to zero!
public int NumberOfCars { get; set; }
// The hidden Car backing field is set to null!
public Car MyAuto { get; set; }
}
با توجه به مقادیر پیشفرض فیلدهای داده، شما میتونید مقدار NumberOfCars رو روی خروجی پرینت بگیرید (که به صورت اتوماتیک مقدار صفر بهش داده شده)، اما اگر بخواهید مستقیما مقدار MyAuto رو طلب کنید، یک استثنای null reference (null reference exception) دریافت خواهید کرد:


کد:
static void Main(string[] args)
{
...
Garage g = new Garage();
// OK, prints defualt value of zero.
Console.WriteLine("Number of Cars: {0}", g.NumberOfCars);
// Runtime error! Backing field is currently null!
Console.WriteLine(g.MyAuto.PetName);
Console.ReadLine();
}
با توجه به اینکه فیلدهای private در زمان کامپایل ساخته میشه، شما نمیتوانید از syntax سی شارپ برای initialize کردن انواع ارجاعی با استفاده از new استفاده کنید. بنابراین شما نیاز خواهید داشت که از constructorها برای ساخته شدن آبجکت از طریق صحیح و ایمن استفاده کنید :


کد:
class Garage
{
// The hidden backing field is set to zero!
public int NumberOfCars { get; set; }
// The hidden backing field is set to null!
public Car MyAuto { get; set; }
// Must use constructors to override default
// values assigned to hidden backing fields.
public Garage()
{
MyAuto = new Car();
NumberOfCars = 1;
}
public Garage(Car car, int number)
{
MyAuto = car;
NumberOfCars = number;
}
}
شما هم مثل من خیلی موافق هستید که این قابلیت جدید زیبایی برای زبان سی شارپ هست، شما میتونید تعداد زیادی از properties ها رو برای یک کلاس با یک syntax ساده تعریف کنید.البته حواستون باشه که اگر نیاز به این داشتید که اعمال اضافی رو بر روی property مورد نظر انجام بدید (مثل اعبتارسنجی داده ها (validation)، نوشتن در event log، تعامل با دیتابیس و ...) نیاز به همون propertyهای معمولی و عادی دات نت دارید و باید زحمت نوشتن property رو به صورت دستی انجام بدید. Automatic properties ای که در سی شارپ 2008 ارائه شده، چیزی بیشتر از encapsulate کردن ساده ی فیلدهای داده نیست.