Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# Generics Inheritance

I have the following class

public class AccountingBase<TItemType> where TItemType : AccountingItemBase

And in my AccountingItemBase i have the following property:

public virtual AccountingBase<AccountingItemBase> Parent { get; set; }

in my AccountingBase, I am trying to do the following

item.Parent = this;

Logically this should work, as TItemType inherits from AccountingItemBase, but instead i get the following error:

> Error 1 Cannot implicitly convert type
> 'TGS.MySQL.DataBaseObjects.AccountingBase<TItemType>'
> to
> 'TGS.MySQL.DataBaseObjects.AccountingBase<TGS.MySQL.DataBaseObjects.AccountingItemBase>'

How can i set the child properties parent property to itself (inside the parent class)

like image 769
Michal Ciechan Avatar asked Feb 25 '23 23:02

Michal Ciechan


1 Answers

No, your intuition is incorrect. It shouldn't work, because generic classes aren't variant in .NET.

Just because TItemType inherits from AccountingItemBase doesn't mean that AccountingBase<TItemType> inherits from AccountingBase<AccountingItemBase>. Suppose AccountingBase<TItemType> had a field of type TItemType. Then if your intuition were correct, you could write:

AccountingBase<SomeSubtype> x = new AccountingBase<SomeSubtype>();
AccountingBase<AccountingItemBase> y = x;
y.SomeField = new OtherSubtype();

That would clearly break type safety, because when looked at as an AccountingBase<SomeSubtype>, the field is meant to be of type SomeSubtype, but you've put a value of type OtherSubtype in there!

Basically, generic variance is a complex topic.

I suggest you read Eric Lippert's long and detailed blog post series for more information. Or I have a video from NDC 2010 which you may find useful. Basically in .NET 4 there's some generic variance, but it's limited.

Now, as to what you can do in your situation:

  • You could create a nongeneric base class which AccountingBase inherits from. That's probably the best idea. Then make the type of the Parent property that nongeneric type.
  • You could make AccountingBase generic in both itself and its parent... but that ends up causing recursion issues, effectively...
like image 124
Jon Skeet Avatar answered Mar 02 '23 19:03

Jon Skeet