Companion SO question: http://stackoverflow.com/questions/28326884/c-sharp-immutable-class-sub-class
Companion SO question: https://stackoverflow.com/questions/28326884/c-sharp-immutable-class-sub-class
Below is a simplified example that can be run in LinqPad that shows the issue.
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;
}
}
Companion SO question: http://stackoverflow.com/questions/28326884/c-sharp-immutable-class-sub-class
Below is a simplified example that can be run in LinqPad that shows the issue.
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;
}
}
Companion SO question: http://stackoverflow.com/questions/28326884/c-sharp-immutable-class-sub-class
If you'd like to run this code, I believe that the ImmutableDictionary
is the only type that requires a non-standard library. You should be able to swap it with a normal Dictionary
.
If you'd like to run this code, I believe that the ImmutableDictionary
is the only type that requires a non-standard library. You should be able to swap it with a normal Dictionary
.