kay*_*tea 4 c# generics entity-framework-core
此代码抛出异常
System.InvalidOperationException:找不到实体类型"List <..>".确保已将实体类型添加到模型中.
private static void Update<T>(DbContext context, ICollection<T> existing, ICollection<T> updated)  // where T: class
{
      context.RemoveRange(existing); 
      updated.ToList().ForEach(existing.Add);
}
但是,如果添加类型约束,则where T: class不会引发异常.为什么是这样?我的印象是C#类型约束没有影响这样的运行时行为.两个版本编译都很好.
这不是运行时行为,而是编译时方法重载分辨率和协方差:
context.RemoveRange(existing);
RemoveRange 方法有两个重载:
RemoveRange(IEnumerable<object> entities)
和
RemoveRange(params object[] entities)
具有类约束允许C#编译器选择重载IEnumerable<object>- 因为ICollection<T>是IEnumerable<T>,并且IEnumerable<T>对于引用类型T是协变的,因此是IEnumerable<object>.  
没有类约束,唯一可用的选项是带params object[]参数的方法.这里有一个params object[]构造的缺点/副作用/陷阱- 每个arg类型不同的参数object[]被视为object并隐式传递为new object[] { arg }.
所以,在前一种情况下,实际的呼叫是
context.RemoveRange((IEnumerable<object>)existing);
而在后一种情况下它是
context.RemoveRange(new object[] { existing });
换句话说,列表作为对象传递,这导致了所讨论的运行时异常.
这同样适用于所有其他Range的方法DbContext类- AddRange,UpdateRange和AttachRange.
| 归档时间: | 
 | 
| 查看次数: | 305 次 | 
| 最近记录: |