I have some classes as follows:
public class RowBase { }
public class SpecificRow : RowBase { }
public class RowListItem<TRow> where TRow : RowBase { }
public class SpecificRowListItem : RowListItem<SpecificRow> { }
And some methods as follows:
public string GetName<TRow>(RowBase row) where TRow : RowBase { }
public string GetName<TRow>(RowListItem<TRow> item) where TRow : RowBase { }
The problem I'm having is that a subclass of RowListItem
fails to match the signature of the second overload. Here are examples:
var foo = new SpecificRow();
var bar = new SpecificRowListItem();
var baz = new RowListItem<SpecificRow>();
string name;
name = GetName(foo); // invokes first overload as expected
name = GetName(baz); // invokes second overload as expected
name = GetName(bar); // does not compile
name = GetName((RowListItem<SpecificRow>)bar); // this alternative invokes the second overload
name = GetName<SpecificRow>(bar); // this alternative also invokes the second overload
The compiler error is
Error CS0311 The type 'ConsoleApplication1.SpecificRowListItem' cannot be used as type parameter 'TRow' in the generic type or method 'Program.GetName(TRow)'. There is no implicit reference conversion from 'ConsoleApplication1.SpecificRowListItem' to 'ConsoleApplication1.RowBase'.
Since SpecificRowListItem
is a subclass of RowListItem<TRow>
with a TRow
that meets the where TRow : RowBase
constraint, I would expect that the compiler would be able to tell that it should match the second overload when provided a parameter as an instance of that class. However, the text of the compiler error indicates that it's attempting to match the first overload (GetName(TRow)
). I'd like to understand why that is, and if there's anything I can do to solve the problem other than the two alternatives that are working. I tried this:
public string GetName<TItem, TRow>(TItem item)
where TItem : RowListItem<TRow>
where TRow : RowBase
Aside from being ugly, it gave me the same problem (appears to match the first overload).