В моем проекте у меня есть структура следующего класса:Почему этот метод расширения работает с дженериками, но не с базовым типом набора?
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()
первая версия делает работа.
Каковы технические детали, которые позволяют использовать общую версию, когда конкретная версия не работает?
В какой строке компилятор дает ошибку? – Gusman
Попробуйте «эту IEnumerable коллекцию» - это должно работать без дженериков из-за ковариации IEnumerable . –
@Dmitry Я подтвердил, что не работает, и существует другой метод расширения, который требует множественных перечислений, поэтому не является вариантом. – Phaeze