Note that there are some explanatory texts on larger screens.

plurals
  1. POHow to make generic class that contains a Set of only its own type or subtypes as Children?
    primarykey
    data
    text
    <pre><code>abstract class Animal { } class Mammal : Animal { } class Dog : Mammal { } class Reptile : Animal { } class AnimalWrapper&lt;T&gt; where T : Animal { public ISet&lt;AnimalWrapper&lt;T&gt;&gt; Children { get; set; } } class Program { public static void Main(string[] args) { var foo = new AnimalWrapper&lt;Mammal&gt;(); foo.Children = new HashSet&lt;AnimalWrapper&lt;Mammal&gt;&gt;(); var child = new AnimalWrapper&lt;Dog&gt;(); foo.Children.Add(child); } } </code></pre> <p>This obviously doesn't compile because of <code>foo.Children.Add(child);</code></p> <p>I'm not sure if the above code is the most <em>clear</em> way to demonstrate what I want to do, so I will try to explain in plain English:</p> <p>I want the ability to have a class whose Children objects are in an <code>ISet</code> of the same generic type. Thus, if I also had <code>var child = new AnimalWrapper&lt;Reptile&gt;();</code> it would, at compile time, fail to do <code>foo.Children.Add(child);</code> because <code>Reptile</code> is not and does not inherit from <code>Mammal</code>. However, obviously, even if it's derived, as shown above, it doesn't work.</p> <p>Ultimately, it'd be nice to be able to say <code>ISet&lt;AnimalWrapper&lt;Animal&gt;&gt; baz = new HashSet&lt;AnimalWrapper&lt;Animal&gt;&gt;();</code> then add a <code>new AnimalWrapper&lt;Mammal&gt;()</code> to that set, and <code>new AnimalWrapper&lt;Reptile&gt;()</code> to the same set. And their children would have a property <code>Children</code> that's an <code>ISet&lt;AnimalWrapper&lt;T&gt;&gt;</code> where it's of its own type, in a way, as described above.</p> <p>Is there any way or am I just expecting too much from C#? Heck I'm confusing myself. :)</p> <p><strong>Edit:</strong> Ok, so I almost figured this out, without <code>AnimalWrapper</code>, but with a base <code>IAnimal</code> interface, it could almost work:</p> <pre><code>interface IAnimal { } abstract class Animal&lt;T&gt; : IAnimal where T : Animal&lt;T&gt; { public ISet&lt;T&gt; Children { get; set; } } class Mammal : Animal&lt;Mammal&gt; { } class Dog : Mammal { } class Reptile : Animal&lt;Reptile&gt; { } class Frog : Reptile { } class Program { public static void Main(string[] args) { var animals = new HashSet&lt;IAnimal&gt;(); // any animal can be in this var mammal = new Mammal(); animals.Add(mammal); mammal.Children = new HashSet&lt;Mammal&gt;(); var dog = new Dog(); mammal.Children.Add(dog); // ok! a dog is a mammal dog.Children = new HashSet&lt;Dog&gt;(); // in theory, OK, but compile time error // because Dog : Mammal, and Mammal defines Animal&lt;Mammal&gt;, therefore Dog's // Children is actually ISet&lt;Mammal&gt;, rather than ISet&lt;Dog&gt; (which is what // I want, recursively apply the T in Animal. Mammal mammal2 = new Mammal(); dog.Children.Add(mammal2); // should be verboten, but is allowed for the // same reason above. } } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

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