Jay*_*mon 12 c# collections nullable
List<int?> listONullables = new List<int?>();
IList degenericed = listONullables;
// This works fine
listONullables.Add(null);
// Run time exception:
// "The value "" is not of type "System.Nullable`1[System.Int32]"
// and cannot be used in this generic collection. Parameter name: value"
degenericed.Add(null);
// Also does not work. Same exception
degenericed.Add((int?)null);
// Also does not work
// EDIT: I was mistaken, this does work
degenericed.Add((int?)1);
// Also does not work
// EDIT: I was mistaken, this does work
degenericed.Add(1);
Run Code Online (Sandbox Code Playgroud)
请参阅上面代码中的注释.
我有点理解这个的原因(当你抛弃泛型时,运行时会尽可能地利用有限的信息).我只是想知道是否有办法解决这个问题,即使它有点像黑客.
当我尝试使用相同的私有实现作为非泛型版本时,问题出现了,所以我可以在必要时解决它(有两个非常类似的实现),但显然如果我能想到这个更好出.
编辑:我上面的最后两个条目不会像我最初说的那样失败.但前两个呢.我在上面的代码中添加了对该效果的评论.
为了详细说明评论中的讨论,似乎List<T>.IList.Add在4.0中,有:
ThrowHelper.IfNullAndNullsAreIllegalThenThrow<T>(item, ExceptionArgument.item);
try
{
this.Add((T) item);
}
catch (InvalidCastException)
{
ThrowHelper.ThrowWrongValueTypeArgumentException(item, typeof(T));
}
Run Code Online (Sandbox Code Playgroud)
2.0具有VerifyValueType,它只检查IsCompatibleObject方法:
VerifyValueType(item);
...
private static bool IsCompatibleObject(object value) {
if( (value is T) || ( value == null && !typeof(T).IsValueType) ) {
return true;
}
return false;
}
Run Code Online (Sandbox Code Playgroud)
后者以简单的方式编写. value不是T(因为null不相同Nullable<int>.HasValue = false).另外,正如@LBushkin所指出的,typeof(T).IsValueType将返回true Nullable<int>,因此右侧也会计算为false.