Использование автоматически реализуемых свойств
Возможности свойств C# позволяют представить часть данных из класса таким образом, что мы получаем чистые данные, независимо от того, как они были установлены и получены. В листинге 4-3 содержится простой пример класса Product
, который мы добавили в папку Models
проекта LanguageFeatures
.
Листинг 4-3: Определение свойства
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace LanguageFeatures.Models
{
public class Product
{
private string name;
public string Name
{
get { return name; }
set { name = value; }
}
}
}
Свойство Name
выделено жирным шрифтом. Выражения в блоке кода get
выполняются при чтении значения свойства, а выражения в блоке кода set
выполняются, когда значение присваивается свойству (специальная переменная value
представляет присвоенное значение). Свойство используется другими классами, как показано в листинге 4-4, который представляет метод действия AutoProperty
, что мы добавили к контроллеру Home
.
Листинг 4-4: Использование свойства
using LanguageFeatures.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace LanguageFeatures.Controllers
{
public class HomeController : Controller
{
public string Index()
{
return "Navigate to a URL to show an example";
}
public ViewResult AutoProperty()
{
// создается новый объект Product
Product myProduct = new Product();
// устанавливается значение свойства
myProduct.Name = "Kayak";
// читается свойство
string productName = myProduct.Name;
// генерируется представление
return View("Result",
(object)String.Format("Product name: {0}", productName));
}
}
}
Вы видите, что значение свойства читается и устанавливается, как обычное поле. Использование свойств предпочтительнее использования полей, потому что вы можете менять выражения в блоках get
и set
без необходимости изменения всех классов, которые зависят от свойства.
Совет
Вы заметили, что в листинге 4-4 мы привели второй аргумент для метода
View
к типуobject
. Это потому что методView
перегружен, то есть принимает два аргументаString
, и это имеет другое значение, чем приниматьString
иobject
. Чтобы избежать не того вызова, мы явно привели второй аргумент. Мы вернемся к методуView
и всем его перегрузкам в главе 18.
Вы можете увидеть результат выполнения этого примера, запустив проект и перейдя к /Home/AutoProperty
(это направлено на вызов метода действия AutoProperty
, и мы получаем шаблон для тестирования каждого примера в этой главе). Поскольку мы передали из метода действия в представление только строку, мы покажем вам результат в виде текста, а не в виде скриншота. Результат листинга 4-4:
Product name: Kayak
Все вроде бы хорошо, но это станет утомительным, когда у нас появится класс, имеющий много свойств, которые служат связующим звеном доступа к полю. И в итоге мы получим нечто излишне громоздкое, как показано в листинге 4-5. Тут представлено, как эти свойства выглядят в файле Product.cs
.
Листинг 4-5: Много определений свойств
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace LanguageFeatures.Models
{
public class Product
{
private int productID;
private string name;
private string description;
private decimal price;
private string category;
public int ProductID
{
get { return productID; }
set { productID = value; }
}
public string Name
{
get { return name; }
set { name = value; }
}
public string Description
{
get { return description; }
set { description = value; }
}
//...и так далее...
}
}
Мы хотим гибкости свойств, но на данный момент нам не нужны пользовательские выражения получения и установки. Решением является автоматически реализуемое свойство, также известное как автоматическое свойство. При помощи автоматического свойства вы можете создать шаблон свойства, поддерживающего поле, без определения поля или указания кода для выражений получения и установки, как показано в листинге 4-6.
Листинг 4-6: Использование автоматически реализуемых свойств
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace LanguageFeatures.Models
{
public class Product
{
public int ProductID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public decimal Price { get; set; }
public string Category { set; get; }
}
}
Есть несколько пунктов, на которые стоит обратить внимание при использовании автоматических свойств. Первое, мы не определяем тело для выражений получения и установки. Второе, мы не определяем поле, поддерживающее свойство. Все это сделает для нас C# компилятор, когда мы построим наш класс. Использование автоматических свойств ничем не отличается от использования обычных свойств; код в методе действия из листинга 4-4 будет работать без каких-либо изменений.
С помощью автоматических свойств мы экономим время на наборе текста, создаем код, который легче читать, и при этом сохраняем ту гибкость, которую предоставляют свойства. Если наступит момент, когда нам нужно будет изменить способ реализации свойства, мы сможем вернуться к обычному формату свойства. Давайте представим, что мы должны изменить способ реализации свойства Name
, как показано в листинге 4-7.
Листинг 4-7: Возвращение от автоматического к обычному свойству
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace LanguageFeatures.Models
{
public class Product
{
private string name;
public int ProductID { get; set; }
public string Name
{
get
{
return ProductID + name;
}
set
{
name = value;
}
}
public string Description { get; set; }
public decimal Price { get; set; }
public string Category { set; get; }
}
}
Примечание
Обратите внимание, что мы должны реализовать выражения получения и установки, чтобы вернуться к обычному свойству. C# не поддерживает смешивание автоматического и обычного стиля выражений получения и установки в одном свойстве.