【问题标题】:How to best design a class that might contain null object如何最好地设计一个可能包含空对象的类
【发布时间】:2015-08-13 11:22:43
【问题描述】:

我即将设计一个类,该类通常不包含对Null 值的引用。它让我想起了可为空的Datetime,它有一个布尔值来指示是否存储了实际值。

        DateTime? dt = new DateTime?();
        if(dt.HasValue)
        {
            //DoStuff
        }

如下设计一个类是一种好的编码习惯吗?

class Computer
{
    public string Name;
    public string ID;
    //...
    public bool IsHiveMind;
    public HiveMindInfo RegInfo;
}
class HiveMindInfo
{
    string SecretLocation;
    int BaudRate;
    int Port;
}

...并使用它...

Computer aComputer = GetComputer(...);
if(aComputer.IsHiveMind)
{
    Network.DoHostileTakeOver(aComputer); //!
}

【问题讨论】:

  • 谁设置了“IsHiveMind”?您应该先将其修改为public bool IsHiveMind{get; private set;}

标签: c#


【解决方案1】:

下面这段代码怎么样? 看来您可以删除 IsHiveMind 变量,因为 HiveMindInfo 变量通过检查其是否为 null 具有相同的含义。

  class Computer
  {
    public string Name;
    public string ID;

    public HiveMindInfo RegInfo;
  }

  class HiveMindInfo
  {
    string SecretLocation;
    int BaudRate;
    int Port;
  }

  Computer aComputer = GetComputer(...);

  if (aComputer != null && aComputer.RegInfo != null)
  {
    Network.DoHostileTakeOver(aComputer);
  }

【讨论】:

    【解决方案2】:

    要回答您的问题,您可以按照建议实现代码。

    另一种方法是考虑以下设计模式:

    示例代码

        interface ITakeOverStrategy
        {
           void Execute();
        }
    
        class KevinFlynnHackerStrategy : ITakeOverStrategy
        {
            public void Execute()
            {
                // a nod to Tron
            }
        }
    
        class NeoHackerStrategy: ITakeOverStrategy
        {
            private readonly HiveMindInfo _hiveMindInfo;
    
            public NeoHackerStrategy(HiveMindInfo info)
            {
               _hiveMindInfo = info;
            }
            public void Execute()
            {
                // Mr. Anderson!
            }
        }
    
        // This is a surrogate class.
        // ... The value returned by String.Empty is often used as a surrogate.
        class IdleStrategy : ITakeOverStrategy
        {
            public void Execute()
            {
                // do nothing
            }
        }
    
        class Computer
        {
            private readonly ITakeOverStrategy _takeoverStrategy ;
    
            public Computer(ITakeOverStrategy strategy)
            {
                _takeoverStrategy = strategy;
            }
    
            public Subjugate()
            {
                // insert epic code here
                _takeoverStrategy.Execute();
            }
         }
    

    然后在代码中的某处使用适当的策略创建Computer 的实例:

    var info = new HiveMindInfo();
    // update instance parameters
    
    var computer = new Computer(new NeoHackerStrategy(info));
    computer.Subjugate();
    

    更新

    2015 年 8 月 13 日 @ 10:13 EST

    我对 structs 的评论不在原问题的范围内,已被删除:

    如果您的类只包含字段/属性,那么我会考虑将它们转换为结构。

    【讨论】:

    • “如果您的类只包含字段/属性,那么我会考虑将它们转换为结构”-您对此有何想法。我总是有点不确定什么时候应该使用结构,什么时候不应该。不过,我认为我以前从未遇到过这种逻辑。
    • 老实说,当我有一个具有属性但没有方法的类时...然后我的下一个想法是:这是一个结构的好候选者。每个实现都是不同的,所以我建议阅读以下内容:When do you use a struct instead of a class?MSDN: Choosing Between Class and Struct
    • 嗯,这似乎并不表明他应该使用结构......事实上他的类有字符串意味着“它的实例大小低于 16 字节”不会被满足。不是一成不变的。当然,似乎没有任何迹象表明缺少方法是使用结构的必要条件。
    • @Chris:我假设示例中的字段/属性只是为大卫的问题提供上下文的占位符。我试图说明的唯一一点是:如果您要拥有一个只有字段/属性的类......那么您可能希望考虑使用结构。就您而言,您选择的数据结构将取决于它的内容。感谢您指出这一点。
    【解决方案3】:

    只需添加 ?到你的对象:

    class Computer
    {
        public string Name;
        public string ID;
        //...
        public HiveMindInfo? RegInfo;
    }
    struct HiveMindInfo
    {
        string SecretLocation;
        int BaudRate;
        int Port;
    }
    

    然后像使用日期时间一样检查它:

    Computer aComputer = GetComputer(...);
    if (aComputer.RegInfo.HasValue)
    { 
         // Do something 
    }
    

    【讨论】:

    • 但是你认为这是一个好的设计吗?与 if(aComputer.RegInfo != null)
    • 只有在 HiveMindInfo 是 struct 时才能执行此操作。你可能不想要这个。引用类的全部意义在于它可以在没有外部帮助类的情况下为空。
    • 你是对的.. 所以大卫需要决定他是要让他的类来构造还是使用布尔属性
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-03
    • 2023-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-28
    相关资源
    最近更新 更多