微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何设计C#/ Java中缺少const?

在尝试模拟我的域时,我遇到了以下问题.让我们看看我们有一件事:

class Thing
{
    public int X { get; set; }
}

东西有一个属性X.然后,有Packs,聚合东西.但该域名要求包装可以容纳的东西有一些限制.例如,Xes的累积值不能高于某个特定限制:

class Pack
{
    private readonly List<Thing> myThings = new List<Thing>();
    private const int MaxValue = 5;

    public void Add(Thing thing)
    {
        if (myThings.Sum(t => t.X) + thing.X > MaxValue)
            throw new Exception("this thing doesn't fit here");
        myThings.Add(thing);
    }

    public int Count
    {
        get { return myThings.Count; }
    }

    public Thing this[int index]
    {
        get { return myThings[index]; }
    }
}

所以我在为条件添加Thing之前检查,但它仍然很容易陷入麻烦:

var pack = new Pack();
pack.Add(new Thing { X = 2 });
pack.Add(new Thing { X = 1 });

var thingOne = new Thing { X = 1 };
var thingTwo = new Thing { X = 3 };

//pack.Add(thingTwo); // exception
pack.Add(thingOne);   // OK

thingOne.X = 5;       // trouble
pack[0].X = 10;       // more trouble

在C中,解决方案是在插入时复制并在索引器中返回const引用.如何在C#(可能还有Java)中围绕这个问题进行设计?我似乎无法想到一个好的解决方案:

>使事物变得不可变 – 但是如果它需要是可变的呢?
>用事件/观察者观察包装中的东西 – 但这意味着Pack强加了Thing的设计;如果东西有更多属性怎么办?然后,由于需要Pack来观察变化,我最终只会遇到一个事件 – 这对我来说似乎很尴尬.

任何想法或首选解决方案?

编辑:

回到这个问题……我接受了Itay的回复.他是对的.
原始问题是,从一个上下文中,您希望Thing对象是不可变的,并且从不同的上下文中,您会希望它是可变的.这需要一个单独的界面……也许吧.我说“也许”,因为大部分时间,Pack都是物品的聚合物(在DDD意义上),因此是对象的所有者 – 这意味着它不应该让你能够改变拥有的对象(或者返回一个副本或返回一个不可变的接口).

很高兴在C中这个特殊的东西可以通过const修饰符轻松处理.如果你想把事情保持在一致的状态,那么看起来好像很少编码.

解决方法

让事情变得不变.

class Thing
{
    public Thing (int x)
    {
       X = x;
    }
    public int X { get; private set; }
}

另外,而不是if(myThings.Sum(t => t.X)thing.X> MaxValue)我认为最好在包中保存一个sum字段,这样你就不必每次重新计算总和.

编辑
对不起 – 我错过了你说你需要它可变的事实.
但是……你的c解决方案将如何运作?我不太了解c但不是c常量引用会阻止对包上实例的更改吗?

EDIT2
使用界面

public interface IThing
{
  int X { get; }
}

public class Thing : IThing
{
  int X { get; set; }
}

class Pack
{
    private readonly List<IThing> myThings = new List<IThing>();
    private const int MaxValue = 5;

    public void Add(IThing thing)
    {
        if (myThings.Sum(t => t.X) + thing.X > MaxValue)
            throw new Exception("this thing doesn't fit here");
        myThings.Add(new InnerThing(thing));
    }

    public int Count
    {
        get { return myThings.Count; }
    }

    public IThing this[int index]
    {
        get { return myThings[index]; }
    }

    private class InnerThing : IThing
    {
      public InnerThing(IThing thing)
      {
        X = thing.X;
      }
      int X { get; private set; }
    }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐