Note that there are some explanatory texts on larger screens.

plurals
  1. POWhy aren't generic type constraints inheritable/hierarchically enforced
    text
    copied!<p>Item class</p> <pre><code>public class Item { public bool Check(int value) { ... } } </code></pre> <p>Base abstract class with generic type constraint</p> <pre><code>public abstract class ClassBase&lt;TItem&gt; where TItem : Item { protected IList&lt;TItem&gt; items; public ClassBase(IEnumerable&lt;TItem&gt; items) { this.items = items.ToList(); } public abstract bool CheckAll(int value); } </code></pre> <p>Inherited class without constraints</p> <pre><code>public class MyClass&lt;TItem&gt; : ClassBase&lt;TItem&gt; { public override bool CheckAll(int value) { bool result = true; foreach(TItem item in this.items) { if (!item.Check(value)) // this doesn't work { result = false; break; } } return result; } } </code></pre> <p>I would like to know why aren't generic type constraints inheritable? Because if my inherited class inherits from base class and passes over its generic type which has a constraint on the base class it automatically means that generic type in inherited class should have the same constraint without explicitly defining it. Shouldn't it?</p> <p>Am I doing something wrong, understanding it wrong or is it really that generic type constraint aren't inheritable? If the latter is true, <strong>why in the world is that</strong>?</p> <h2>A bit of additional explanation</h2> <p>Why do I think that generic type constraints defined on a class should be inherited or enforced on child classes? Let me give you some additional code to make it bit less obvious.</p> <p>Suppose that we have all three classes as per above. Then we also have this class:</p> <pre><code>public class DanteItem { public string ConvertHellLevel(int value) { ... } } </code></pre> <p>As we can see this class does not inherit from <code>Item</code> so it can't be used as a concrete class as <code>ClassBase&lt;DanteItem&gt;</code> (forget the fact that <code>ClassBase</code> is abstract for now. It could as well be a regular class). Since <code>MyClass</code> doesn't define any constraints for its generic type it seems perfectly valid to have <code>MyClass&lt;DanteItem&gt;</code>...</p> <p>But. This is why I think generic type constraints should be inherited/enforced on inherited classes just as with member generic type constraints because if we look at definition of <code>MyClass</code> it says:</p> <pre><code>MyClass&lt;T&gt; : ClassBase&lt;T&gt; </code></pre> <p>When <code>T</code> is <code>DanteItem</code> we can see that it automatically can't be used with <code>MyClass</code> because it's inherited from <code>ClassBase&lt;T&gt;</code> and <code>DanteItem</code> doesn't fulfill its generic type constraint. I could say that **generic type on <code>MyClass</code> depends on <code>ClassBase</code> generic type constraints because otherwise <code>MyClass</code> could be instantiated with any type. But we know it can't be.</p> <p>It would be of course different when I would have <code>MyClass</code> defined as:</p> <pre><code>public class MyClass&lt;T&gt; : ClassBase&lt;Item&gt; </code></pre> <p>in this case T doesn't have anything to to with base class' generic type so it's independent from it.</p> <p>This is all a bit long explanation/reasoning. I could simply sum it up by:</p> <blockquote> <p>If we don't provide generic type constraint on <code>MyClass</code> it implicitly implies that we can instantiate <code>MyClass</code> with <strong>any concrete type</strong>. But we know that's not possible, since <code>MyClass</code> is inherited from <code>ClassBase</code> and that one has a generic type constraint.</p> </blockquote> <p>I hope this makes much more sense now.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload