С# эквивалент для макросов на С++ и использование Auto <> Свойства
У меня есть код автоинверсии, который я хотел бы применить к примерно 15 свойствам в довольно большом классе. Код похож на следующий, но тип отличается для каждого экземпляра:
protected ComplexType _propertyName;
public ComplexType PropertyName
{
get
{
if (_propertyName == null) {
_propertyName = new ComplexType();
}
return _propertyName;
}
}
Чтобы повторить это на С++ (как есть ~ 15 экземпляров), я бы использовал макрос препроцессора, но я заметил, что С# не поддерживает их.
Мне интересно, есть ли у кого-нибудь рекомендация о том, как сделать это на С#?
Ответы
Ответ 1
Это может сделать вещи немного опрятными, вы можете добавить этот метод, чтобы ввести некоторое повторное использование:
protected ComplexType _propertyName;
public ComplexType PropertyName
{
get
{
return GetProperty(ref _propertyName);
}
}
.
.
private T GetProperty<T>(ref T property) where T : new()
{
if (property == null)
property = new T();
return property;
}
Ответ 2
Вы можете использовать оператор ??
для упрощения кода в одну строку:
protected ComplexType _propertyName;
public ComplexType PropertyName
{
get
{
return _propertyName ?? (_propertyName = new ComplexType());
}
}
В качестве побочного примечания я, вероятно, избегал бы защищенных полей. Если вам нужно установить свойство из производного класса, я бы скорее создал защищенный сеттер.
Ответ 3
Вы можете создать общую структуру, которая обрабатывает ленивое создание:
public struct LazyCreate<T> where T : class, new() {
private T _value;
public T Value {
get {
if (_value == null) {
_value = new T();
}
return _value;
}
}
}
protected LazyCreate<ComplexType> _propertyName;
public ComplexType PropertyName {
get {
return _propertyName.Value;
}
}
Ответ 4
Даже если это не решит вашу проблему напрямую, вы можете взглянуть на новый класс Lazy<T>
, который поставляется с .NET 4.0. Он специально разработан для ленивых сценариев инициализации.
Ответ 5
Вы можете использовать сильно забытый T4 (текстовый шаблон
Transformation Toolkit) для генерации кода. Он включен
с Visual Studio 2008.
Был эпизод 2009-06.NET Rocks:
" Питер Вогель использует генерацию кода".
Ответ 6
Вы можете реализовать ленивую инициализацию способом, подобным этому:
public class Lazy<T> where T : new()
{
private T _value;
private bool _isInitialized;
private T GetValue()
{
if (!_isInitialized)
{
_value = new T();
_isInitialized = true;
}
return _value;
}
public static implicit operator T (Lazy<T> t)
{
return t.GetValue();
}
}
который позволит вам написать код следующим образом:
private Lazy<ComplexType> _lazyCt = new Lazy<ComplexType>();
public ComplexType LazyCt
{
get { return _lazyCt; }
}
Специфика инициализации не имеет значения, я написал ее так, чтобы показать, что вы можете сделать ее прозрачно конвертируемой в нелатную версию и выполнить инициализацию при первом преобразовании.:)
Ответ 7
Попробуйте использовать Hashtable или словарь < string, ComplexType > , чтобы сгруппировать все свойства. Что-то вроде этого:
protected Dictionaty<string, ComplexType> _properties = new Dictionaty<string, ComplexType>();
public ComplexType Property(string name)
{
get
{
if (!properties.ContainsKey(name))
_properties[name] = new ComplexType();
return __properties[name];
}
}