What determines which constructor is used if a Generic class has 2 constructors:
One takes (T data)
, and another (string errorMessage)
.
And an instance is created with type string?
For me it seems to be using the constructor with parameter (string errorMessage)
instead of (T data)
.
- I'm wondering why?
- And is there a way to make it use the generic
(T data)
constructor instead?
Luckily I don't need to in my case, but I don't know how I would.
public class GenericClass<T>
{
public T Data { get; set; }
public string ErrorMessage { get; set; }
public GenericClass(T data)
{
Data = data;
}
public GenericClass(string errorMessage)
{
ErrorMessage = errorMessage;
}
}
New instance is created with either:
new GenericClass<string>("some error");
Or:
new GenericClass<string>("some data");
I thought it would give an Ambiguous Constructor error, but it doesn't.
It always uses the (string errorMessage)
constructor.
CodePudding user response:
Your problem is not specific to constructors. The same behaviour can be observed in case of method overloading. For example:
public class ClassA
{
public static void MethodA<T>(T data)
{
Console.WriteLine("Generic version has been called");
}
public static void MethodA(string errorMessage)
{
Console.WriteLine("String version has been called");
}
}
The related documentation can be found here: Overload resolution.
You can enforce the call of the other constructor if you are taking advantage of named parameters feature of C#:
new GenericClass<string>(data: "some data");
Of course this technique works only if the parameter names are different.
So, this won't work if you would define your class like this:
public class GenericClass<T>
{
public T Data { get; set; }
public string ErrorMessage { get; set; }
public GenericClass(T _)
=> Data = _;
public GenericClass(string _)
=> ErrorMessage = _;
}
A solution could be for this problem
- introduce factory methods
- change the properties'
set
toinit
- and create a
private ctor
public class GenericClass<T>
{
public T Data { get; init; }
public string ErrorMessage { get; init; }
public static GenericClass<T> CreateWithData(T _)
=> new GenericClass<T> { Data = _ };
public static GenericClass<string> CreateWithError(string _)
=> new GenericClass<string> { ErrorMessage = _ };
private GenericClass() {}
}