在我的项目中,我有以下类结构:
public interface IUpdateableModel
{
ModelState State { get; set; }
void ResetState();
}
public abstract class UpdateableModel : IUpdateableModel
{
public ModelState State { get; set; }
public void ResetState()
{
//Perform reset logic
}
}
public class MyUpdateableClass : UpdateableModel
{
//Some properties.
}
现在我正在尝试添加一些扩展方法,以便与IUpdateable
:
public static class UpdateableModelExtensions
{
public static bool HasUnsavedChanges(this IList<IUpdateableModel> collection)
{
return collection.Any(x => x.State != ModelState.Unmodified);
}
public static void ResetItemStates<T>(this IList<T> collection) where T : IUpdateableModel
{
var itemsToRemove = collection.Where(x => x.State == ModelState.New).ToList();
foreach (var item in itemsToRemove)
{
collection.Remove(item);
}
var itemsToAdd = collection.Where(x => x.State == ModelState.Deleted).ToList();
foreach (var item in itemsToAdd)
{
item.State = ModelState.Unmodified;
}
var itemsToReset = collection.Where(x => x.State == ModelState.Modified).ToList();
foreach (var item in itemsToReset)
{
item.ResetState();
}
}
}
正如在List<MyUpdateableClass>
上使用此代码时编写的,编译错误会导致类型不匹配。
public class MyClass
{
public IList<MyUpdateableClass> Items {get; set;}
public void MyMethod()
{
if(Items.HasUnsavedChanges()) //Compiler error
{
//Do some stuff
}
}
}
编译错误是:
'IList<MyUpdateableModel>' does not contain a definition for
'HasUnsavedChanges' and the best extension method overload
'UpdateableModelExtensions.HasUnsavedChanges(IList<IUpdateableModel>)'
requires a receiver of type 'IList<IUpdateableModel>'
如果扩展方法更改为IList<UpdateableModel>
但是,如果我改为使用泛型来实现它,它可以正常工作:
public static bool HasUnsavedChanged<T>(this IList<T> collection)
where T : IUpdateableModel
{
return collection.Any(x => x.State != ModelState.Unmodified);
}
此外,如果我将使用情况更改为Items.Cast<IUpdateableModel>().ToList()
,则第一个版本可以正常运行。
那么,当具体版本没有时,哪些技术细节允许通用版本工作?
答案 0 :(得分:4)
这是因为IList内容比签名允许的更具体。这可能会导致违反隐含合同。
IList<IUpdateableModel>
的合同是IUpdateableModel
的任何实施者都必须能够添加到列表中。 List<ImplementationOfUpdateableModel>
无法做到这一点,因为您只能添加ImplementationOfUpdateableModel
类型的对象。
泛型版本有效,因为它允许该方法接受IList更具体的对象内容。