generics in constructors  
Author Message
fwolf





PostPosted: Visual C# Language, generics in constructors Top

Hello,

I have a question about generics in constructors. Assume I have two constructors, e.g.:

public Constructor1(string param1, string param2) { ... }
public Constructor2(T param1, string param2) { ... }

This will compile without problems (by contrast, I'd get a compile error if I had "public Constructor2(string param1, string param2)" because there would be two constructors with "string, string").

However, if at runtime I call Constructor2 with the generic parameter as a string, I get runtime problems (because Constructor1 and Constructor2 cannot be distinguished).

Does anyone know how to deal with this in a clean way I know that I could, for example, change Constructor2 to something like "Constructor2(T param1, string param2, bool hasGenericParam)", but I think this is somewhat ugly, particularly if I had more than one generic parameter).

Any help on this would be greatly appreciated. Thank you in advance.



Visual C#6  
 
 
Lepaca





PostPosted: Visual C# Language, generics in constructors Top

The compiler chooses always the most specific method... in this case the method without generic...

If you want call Constructor2 also with T=String, then simply remove Constructor1...


 
 
RizwanSharp





PostPosted: Visual C# Language, generics in constructors Top

You can put a Constraint on Type parameters on Generic types in C# using a where...

On class level you can do something like this:

class SomeClass<T> where T : struct

etc...

But it depends that what may be the constraint..... As per your requirement, There may be a single class but multiple interfaces.

See MSDN for more help.

Best Regards,

Rizwan



 
 
James Curran





PostPosted: Visual C# Language, generics in constructors Top

First of all, the problem isn't as simple as you describe. If you were to write:

public class MyClass2
{

public MyClass2(string a, string b)
{
}
public MyClass2<T>(T a, string b)
{
}
}

YOu'd get a syntax error, because you can't make a constructor a generic method. So, you'd have to make it a generic class:



public
class MyClass2<T>
{
public MyClass2(T a, string b)
{
}
public MyClass2(string a, string b)
{
}
}

And then write

MyClass2<string> a = new MyClass2<string>("aaaa", "bbbb");

to cause the problem (MyClass(string, string) is called instead of MyClass(T, string)).

BUt, in the end, the only way to make that work is change the parameter signatures. I'd probably add the parameter to the (string, string) case, but you'll have to decide for yourself.



 
 
fwolf





PostPosted: Visual C# Language, generics in constructors Top

first of all, thank you for your feedback (thanks to everyone who replied in this thread so far). What you describe is what I was wondering if I could avoid: changing the parameter signature. It seems there is no better way for dealing with this.

I just brought up this issue because I think it might be relevant to a number of issues -- not just constructors, but, more general, overloading with generics.

Thanks again to everyone for their replies.


 
 
Lepaca





PostPosted: Visual C# Language, generics in constructors Top

I don't understand...
if you have

public void p(string param1, string param2) { ... }
public void p( T param1, string param2) { ... }

and T is string, why do you want call p n.2
But if you want this...

Class xxxx <T>
{
Public void a(T val)
{
b(val)
}
Public void a(String val)
{
If (typeof(T).ToString = "System.String")
{
b(val)
}
Else
{
[...]
}
}

Private
void b(Object val)
{
[...]
}
}

b is called by a-specific only when T is string...


 
 
louthy





PostPosted: Visual C# Language, generics in constructors Top

The pragmatic side of me says do this:

  public class Test<T>
  {
   // Just one constructor
   public Test(T param1, string param2)
   {
    if (param1 is string)
    {
     InitialiseFromString(param1.ToString(), param2);
    }
    else
    {
     InitialiseFromGeneric(param1, param2);
    }
   }

   private void InitialiseFromString(string param1, string param2)
   {
    // do your init here...
   }

   private void InitialiseFromGeneric(T param1, string param2)
   {
    // do your init here...
   }

  }

This passes means you just have one generic constructor, and no possibility for confusion.  Also the Initialise methods have different names, so they can't possibly be mistaken by the compiler.  It's not the prettiest code, but it is the most effective for the example you have given.