如何公开依赖于另一个值的值

时间:2017-11-07 13:38:42

标签: c# properties

我从服务器收到某类产品。这些产品都有ID。相关部分是这样的:

if(product.Id == -1)

在app本身,我也使用ID为-1来表示默认/ null选项。有几种选择,例如“与父母一样使用”的ID为-2。起初我以最原始的方式检查了这个。

public bool IsDefault
{
    get { return Id == -1; }
}

这不是真正干净的代码,因此我将其更改为产品上的bool属性:

bool isDefault = id == -1;
Product product = new Product(id, isDefault);

然后我注意到,因为整个类是不可变的,所以这个bool可以只是一个可以在构造时分配的自动属性。

public interface IProduct
{
    int Id{get;}
    bool IsDefault{get;}
}


public class Product : IProduct
{
    public Product(int id)
    {
        Id = id;
    }

    public int Id { get; private set; }

    public bool IsDefault { get{ return false; } }
}


public class DefaultProduct : IProduct
{
    public int Id { get{ return -1; }
    public bool IsDefault { get{ return true; } }
}

目前我尝试了一种使用接口并拥有默认产品的实现方法,如下所示:

class AutoDiscovery : IDisposable
{
    private UdpClient Udp;
    private static IPEndPoint BroadcastEP = new IPEndPoint(IPAddress.Broadcast, 12345);
    private List<byte> AutoDiscoverPacket = new List<byte>();

    private bool _IsDisposed = false;
    public bool IsDisposed
    {
        get { return _IsDisposed; }
        private set { _IsDisposed = value; }
    }

    public AutoDiscovery()
    {
        Udp = new UdpClient();
        Udp.ExclusiveAddressUse = false;
        Udp.EnableBroadcast = true;
        Udp.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
        Udp.Client.Bind(new IPEndPoint(IPAddress.Any, 12345));
        ReceiveDataAsync(ReceiveDataCallback);

        AutoDiscoverPacket.AddRange(new byte[] { 0x14, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x03, 0x00, 0x00 });
        AutoDiscoverPacket.AddRange(Encoding.ASCII.GetBytes("SomeStaticString"));
        while (AutoDiscoverPacket.Count < 123)
        {
            AutoDiscoverPacket.Add(0x00);
        }
    }


    public void Discover()
    {
        if (IsDisposed) { throw new ObjectDisposedException("AutoDiscovery"); }
        Udp.Send(AutoDiscoverPacket.ToArray(), AutoDiscoverPacket.Count, BroadcastEP);
    }
}

现在,最后三个示例(检查属性/构造函数参数/接口实现)对我来说似乎同样“干净”,我认为没有任何优势可以超过其他人。

是否有任何好的论据(除了与个人意见相比)优先于其他人?

3 个答案:

答案 0 :(得分:0)

您不需要产品的默认版本。

您可以创建不带参数的构造函数来创建默认对象。

答案 1 :(得分:0)

你过度思考它,并用接口过度复杂化。

我会根据传递的Id参数在构造函数中设置IsDefault。甚至可能为此添加一个默认值,这样您就可以在没有参数的情况下实例化该类,它应该是一个默认产品。

public class Product
{
    public Product(int id = -1)
    {
        Id = id;
        IsDefault = id == -1;
    }

    public int Id { get; private set; }
    public bool IsDefault { get; private set; }
}

答案 2 :(得分:0)

虽然这说起来容易做起来难,但答案来自于重新评估某些事物实际上和/或代表的基本假设。

ID X指向ID为X的产品。这是该ID的目的,并将其用于不同目的是滥用它。所以

if(product.Id == -1)

public bool IsDefault
{
    get { return Id == -1; }
}

两个语义错误。 isDefault是该类配置的不同部分。

该类的部分配置也是解除最后一个选项的原因。新类应该封装新行为。为了实现相同的行为,仅针对不同的配置,应该使用不同的配置创建类。

现在,将IsDefault = id == -1;置于构造函数中是一种诱人的解决方案。但是,这会违反SRP。 Product类应该更改的一个原因是产品做什么更改。如果明天默认产品的ID更改为-32,则产品的功能没有变化。

但是,我有一个ProductParser类,其中Product被创建。 类应该更改的一个原因是如何将产品从服务器解析为我的应用程序更改 - 这正是我们当时所做的更改。

因此,根据干净的代码,这里只有一种正确的方法:在创建它的任何地方确定isDefault并将其传递给Product的构造函数,这将它保持为不可变的值。 / p>