5

I have a generic class. The constructor needs to accept an argument that is another instance of the same class. The problem is that the other instance can have a different generics type.

Looks like C# allows me to have a method with it's own generics type, but this doesn't appear allowed for the constructor.

public class MyClass<T>
{
    public MyClass<T2>(MyClass<T2> parent = null)
    {
    }

    // ... Additional stuff
}

The code above tells me T2 is undefined. It doesn't accept it as a method type.

One approach would be to add a second generic type to my class. But this is awkward and, in many cases, the argument will be null and there is not type.

Does anyone see a simple way around this?

Jonathan Wood
  • 65,341
  • 71
  • 269
  • 466
  • 2
    maybe `public class MyClass` – Slai Aug 28 '16 at 22:33
  • What is it your trying to do by creating this class? – jdphenix Aug 28 '16 at 22:35
  • @Slai I was thinking that as well but that lead to a cycle I couldn't seem to break out of. lol – Nkosi Aug 28 '16 at 22:36
  • 1
    @jdphenix: Sorry, I don't see the relevance of that. I'm not new to programming and I have a hundred ways I could write this. But the way I'd like to write it best requires the technique described in my question. – Jonathan Wood Aug 28 '16 at 22:54
  • 3
    Right - well, then I really don't see how your question isn't really just an XY problem. I'm also not sure what my question has to do with your experience or familiarity with ways to implement whatever it is you're doing. – jdphenix Aug 28 '16 at 23:07
  • @jdphenix: As further indicated by your XY Problem comment, you appear to feel that I'm on the wrong track. That suggests you think I lack knowledge and/or experience. If I could take this approach to whatever I'm doing, it would simplify my solution. But it doesn't seem supported by the language without some contortions. If you think a description of what I'm doing is in fact relevant, please share how it is. – Jonathan Wood Aug 29 '16 at 00:13

2 Answers2

5

Generic constructors aren't allowed. However, you can use a generic factory method instead.

public class MyClass<T>
{
    public int Id { get; private set; }
    public int? ParentId { get; private set; }

    public static MyClass<T> Create(int id)
    {
        return Create<object>(id, null);
    }

    public static MyClass<T> Create<T2>(int id, MyClass<T2> parent = null)
    {
        var current = new MyClass<T>();
        current.Id = id;
        current.ParentId = parent?.Id;
        return current;
    }

    private MyClass()
    {
    }

    // ... Additional stuff
}

Sample use:

var intClass = MyClass<int>.Create(55);
var charClass = MyClass<char>.Create(234, intClass);
// charClass.ParentId is 55

This is only possible if you do not need to access any generic members of parent outside the factory method. If you do, you'd be better off abstracting it through a non-generic interface or base class.

Douglas
  • 53,759
  • 13
  • 140
  • 188
4

You are correct. Generic constructors aren't supported.

You could probably try the following:

Create a lower level common interface

public interface IMyClass {
    //...some common stuff
    IMyClass Parent { get; set; }
}

And use that as the common link between the types

public class MyClass<T> : IMyClass {
    public MyClass(IMyClass parent = null) {
        Parent = parent;
    }
    public IMyClass Parent { get; set; }    
    // ... Additional stuff
}
Nkosi
  • 235,767
  • 35
  • 427
  • 472