I would like to know why the generic method below does not compile (C# 4.0). Neither my colleagues nor me can figure it out.
The compiler complains that this which is a SelectableRowBase cannot be converted to a TItem which is constrained to derive from SelectableRowBase. If I put an explicit cast everything works (and that is what I checked in source control), but I would like to know why the compiler is complaining here.
Is that a compiler error? Am I missing something?
public class SelectableRowBase
{
public void AddToSelectedListWhenIsSelectedChanges<TItem>
(ObservableCollection<TItem> selectedList)
where TItem : SelectableRowBase
{
// Causes error:
// The best overloaded method match for
// 'System.Collections.ObjectModel.Collection<TItem>.Add(TItem)'
// has some invalid arguments
// Argument 1: cannot convert from SelectableRowBase' to 'TItem'
Action actionOnSelected = () => selectedList.Add(this);
Action actionOnDeselected = () => selectedList.Remove(this);
// Compiles and works fine
// only difference is the explicit cast
Action actionOnSelected = () => selectedList.Add((TItem)this);
Action actionOnDeselected = () => selectedList.Remove((TItem)this);
}
}
It’s entirely reasonable for it not to work.
You’re trying to add an instance of a base type to a collection of a potential derived type.
That’s like trying to write:
That would violate type safety.
Basically, there’s absolutely no guarantee that
thisis an instance ofTItem. It might be which is why the cast compiles – but equally it might not be. That cast is a really bad idea – it’s leaving type safety to execution time, which is the opposite of the purpose of generics.