【问题标题】:C# Equivalent for C++ Macros and using Auto<> PropertiesC# 等效于 C++ 宏并使用 Auto<> 属性
【发布时间】:2009-09-07 09:47:27
【问题描述】:

我有一些自动实例化代码,我想将其应用于一个相当大的类中的大约 15 个属性。代码与以下类似,但每个实例的类型不同

protected ComplexType _propertyName;
public ComplexType PropertyName
{
    get
    {
        if (_propertyName == null) {
            _propertyName = new ComplexType();
        }

        return _propertyName;
    }
}

要在 C++ 中重复此操作(因为有大约 15 个实例),我会使用 预处理器宏,但我注意到 C# 不支持它们。

我想知道是否有人对如何在 C# 中干净利落地提出建议?

【问题讨论】:

    标签: c# properties coding-style


    【解决方案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());
        }
      }
      

      作为旁注,我可能会避免使用受保护的字段。如果您需要从派生类设置属性,我宁愿创建一个受保护的设置器。

      【讨论】:

      • 根据我在 C++ 方面的经验,如果您想在不放弃成员保护的情况下对应用进行未来验证,我通常发现将所有内容设置为“受保护”而不是“私有”是一个更好的举措。我很少使用私人的。
      • @Kelix:但你实际上是通过保护字段来放弃成员保护。现在任何派生类都可以完全访问您的字段。这有点类似于拥有公共字段,只是只有派生类而不是所有类都可以访问这些字段。
      • @Martin:是的,这是想要的效果。除非我明确不想允许在派生类中访问,否则我会将其标记为“受保护”。一般来说,如果你要努力派生一个类,无论如何你都会想以某种方式添加或改变行为,那么为什么不提供不受限制的访问呢?显然,如果这是一个可公开访问的接口(例如类库),那么“私有”会更合适。我只是不喜欢在不必要的地方限制访问。
      • @Kelix - 你倒退了。你应该在想“我不喜欢在没有必要的地方允许访问”。
      【解决方案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;
          }
      }
      

      【讨论】:

      • 我会使用通用结构来避免在堆上创建更多对象。
      • 当 T 是一个结构体时会发生什么? new() 不排除这种可能性,并且 AFAIK 结构不能为空。 :)
      • @Rytmis:要处理结构,它必须有一个单独的标志来指示值是否已创建,但是结构的惰性初始化通常似乎是一个糟糕的设计选择......我'将添加一个约束,使其只能与引用类型一起使用。
      • @Ian:好点,我在我们的库中挖出了一个非常相似的通用结构作为参考,将类更改为结构应该没有任何问题。我把它写成一个类,因为结构通常更复杂,难以正确实现。
      【解决方案4】:

      即使它不能直接解决您的问题,您也可以看看 .NET 4.0 附带的新 Lazy&lt;T&gt; 类。它专为延迟初始化场景而设计。

      【讨论】:

        【解决方案5】:

        您可以使用被忽视的T4(文本模板 Transformation Toolkit) 来生成代码。包括在内 使用 Visual Studio 2008。

        2009-06 年 .NET Rocks 有一集关于它: Peter Vogel uses Code Generation.

        【讨论】:

          【解决方案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】:

            尝试使用 HashtableDictionary 对所有属性进行分组。像这样的:

            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];
                }
            }
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2015-01-12
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2010-12-19
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多