Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/268.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么这个扩展方法只能处理泛型而不能处理集合基类型?_C#_Generics_Inheritance - Fatal编程技术网

C# 为什么这个扩展方法只能处理泛型而不能处理集合基类型?

C# 为什么这个扩展方法只能处理泛型而不能处理集合基类型?,c#,generics,inheritance,C#,Generics,Inheritance,在我的项目中,我有以下类结构: public interface IUpdateableModel { ModelState State { get; set; } void ResetState(); } public abstract class UpdateableModel : IUpdateableModel { public ModelState State { get; set; } public void ResetState() {

在我的项目中,我有以下类结构:

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();
        }
    }
}
public静态类updateablemodelex0
{
公共静态bool HasUnsavedChanges(此IList集合)
{
返回集合.Any(x=>x.State!=ModelState.Unmodified);
}
公共静态void resetItemState(此IList集合),其中T:IUpdateableModel
{
var itemsToRemove=collection.Where(x=>x.State==ModelState.New).ToList();
foreach(itemsToRemove中的变量项)
{
收集。移除(项目);
}
var itemsToAdd=collection.Where(x=>x.State==ModelState.Deleted).ToList();
foreach(itemsToAdd中的var项)
{
item.State=ModelState.Unmodified;
}
var itemsToReset=collection.Where(x=>x.State==ModelState.Modified).ToList();
foreach(itemsToReset中的var项)
{
item.ResetState();
}
}
}
正如在
列表中使用此选项时所写的那样,会产生类型不匹配的编译器错误

public class MyClass
{
    public IList<MyUpdateableClass> Items {get; set;}

    public void MyMethod()
    {
         if(Items.HasUnsavedChanges()) //Compiler error
         {
            //Do some stuff
         }
    }
}   
公共类MyClass
{
公共IList项{get;set;}
公共方法()
{
if(Items.HasUnsavedChanges())//编译器错误
{
//做点什么
}
}
}   
编译器错误为:

 '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”不包含的定义
“HasUnsavedChanges”和最佳扩展方法重载
'UpdateableModelExchanges.HasUnsavedChanges(IList)'
需要“IList”类型的接收器
如果将扩展方法更改为
IList

但是,如果我改为使用泛型来实现这一点,它可以很好地工作:

public static bool HasUnsavedChanged<T>(this IList<T> collection) 
where T : IUpdateableModel
    {
        return collection.Any(x => x.State != ModelState.Unmodified);
    }
public static bool hassunsavedchanged(此IList集合)
其中T:IUpdateableModel
{
返回集合.Any(x=>x.State!=ModelState.Unmodified);
}
另外,如果我将用法更改为
Items.Cast().ToList()
,则第一个版本可以工作


那么,当具体版本不起作用时,允许通用版本起作用的技术细节是什么呢?

这是因为IList内容比签名更具体。这可能导致违反默示合同

IList
的合同是,必须能够将
IUpdateableModel
的任何实现者添加到列表中。这对于
列表
是不可能的,因为您只能添加类型为
ImplementationOfUpdateableModel
的对象


通用版本之所以有效,是因为它允许方法接受更具体对象内容的IList

编译器在哪一行给出错误?请尝试“this IEnumerable collection”-由于IEnumerable的协变性,这在没有泛型的情况下应该可以工作。@Dmitry我已经确认这不起作用,还有另一个扩展方法需要多个枚举,因此不是一个选项。@Gusman我正在键入一个编辑,以了解有关用法的更多详细信息。请提供一个。现在出现错误是完全可以理解的,因为
列表
不是
IList
,而是带有
IEnumerable
类型的参数,它应该可以工作。。。至少如果您使用的是.NET 4.0或更高版本。出于某种原因,这是有道理的。我没有将这些点连接起来。我认为“这可能导致违反默示合同”这句话应该改写为“这确实会导致违反显式合同”