【发布时间】:2015-02-04 16:49:09
【问题描述】:
我有一个不可变类型,我想创建一个可以访问所有相同方法的子类。
但是,由于您必须实现不可变类,基类方法返回我的父类型,而不是我的子类型。是否可以创建一个不可变的类,该类可以具有返回子类的子类?
下面是在 LinqPad 中运行的示例代码,用于演示问题
void Main()
{
var immutable = new MyImmutable(new Dictionary<ImmutableKey, decimal>{
{ ImmutableKey.Key1, 1 },
{ ImmutableKey.Key2, -5 },
{ ImmutableKey.Key3, 1.25m },
});
var immutable2 = new MyImmutable(new Dictionary<ImmutableKey, decimal>{
{ ImmutableKey.Key1, 1 },
{ ImmutableKey.Key2, 2 },
{ ImmutableKey.Key3, 3 },
});
var added = immutable.Apply((a, b) => a + b, immutable2);
added[ImmutableKey.Key1].Dump();
added[ImmutableKey.Key2].Dump();
added[ImmutableKey.Key3].Dump();
var subImmutable1 = new SubImmutable(1, new Dictionary<ImmutableKey, decimal>{
{ ImmutableKey.Key1, 1 },
{ ImmutableKey.Key2, -5 },
{ ImmutableKey.Key3, 1.25m },
});
var subImmutable2 = new SubImmutable(1, new Dictionary<ImmutableKey, decimal>{
{ ImmutableKey.Key1, 1 },
{ ImmutableKey.Key2, 2 },
{ ImmutableKey.Key3, 3 },
});
var subImmutableAdded = subImmutable1.Apply((a, b) => a + b, subImmutable2);
subImmutableAdded.GetType().Name.Dump(); //prints MyImmutable, it's not a SubImmutable
//after adding two SubImmutables, the type is changed back to the base type
var asSub = (SubImmutable)subImmutableAdded; // Unable to cast object of type 'MyImmutable' to type 'SubImmutable', SomeOtherValue was lost.
}
public enum ImmutableKey
{
Key1,
Key2,
Key3
}
public class MyImmutable
{
protected static readonly IEnumerable<ImmutableKey> AllKeys = Enum.GetValues(typeof(ImmutableKey)).Cast<ImmutableKey>();
private Dictionary<ImmutableKey, decimal> _dict { get; set; }
public MyImmutable(Dictionary<ImmutableKey,decimal> d)
{
_dict = d;
}
public decimal this[ImmutableKey key]
{
get
{
if (_dict == null || !_dict.ContainsKey(key))
return 0;
return _dict[key];
}
}
public MyImmutable Apply(Func<decimal, decimal, decimal> aggFunc, MyImmutable y)
{
var aggregated = new Dictionary<ImmutableKey, decimal>(AllKeys.Count());
foreach (ImmutableKey bt in AllKeys)
{
aggregated[bt] = aggFunc(this[bt], y[bt]);
}
return new MyImmutable(aggregated);
}
}
public class SubImmutable : MyImmutable
{
public int SomeOtherValue { get; set; }
public SubImmutable(int someValue, Dictionary<ImmutableKey,decimal> d)
:base(d)
{
SomeOtherValue= someValue;
}
}
输出:
2
-3
4.25
我的不可变
InvalidCastException:无法将“MyImmutable”类型的对象转换为“SubImmutable”类型。
有没有一种方法可以让我拥有一个继承的不可变类型,它可以继承基类型中的所有方法,而不必重新实现它们?
Companion CodeReview 问题:https://codereview.stackexchange.com/questions/79380/inheriting-methods-of-an-immutable-type
【问题讨论】:
-
你应该看看微软的
ImmutableCollections。 -
你可以使用
new的方法隐藏。但根据我的经验,继承和不变性并不能很好地融合在一起。您宁愿将只读接口与密封的具体类一起使用。 -
@CodesInChaos 使用不可变类型的全部优势在于,您实际上可以依赖永不改变的类型。如果有允许类型发生变异的方法,即使它们被隐藏,这些假设最终也会被违反。
-
@Greg 我在实际实现中使用了 ImmutableDictionary,这是一个示例。
标签: c# inheritance immutability