С# эквивалент для макросов на С++ и использование 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. Он специально разработан для ленивых сценариев инициализации.

Ответ 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];
    }
}