Reputation: 8973
public static object GetObject(int x)
{
return new object { };
}
public static object GetObject(string x)
{
return new object { };
}
public static void ProcessObject<T>(T x) where T : int, string <= got error here:
{
object o = GetObject(x);
}
Got error "A type used as a constraint must be an interface, a non-sealed class or a type parameter."
How can I rewrite the code to get it work without write ProcessObject(int x)
and ProcessObject(string x)
twice?
Upvotes: 1
Views: 600
Reputation: 56536
So what you have now (according to accepted answer and your comments) is:
public static void ProcessObject<T>(T x)
{
object o;
if (typeof(T) == typeof(int))
o = GetObject((int)(object)x);
else if (typeof(T) == typeof(string))
o = GetObject((string)(object)x);
else
throw new Exception();
// do stuff with o
}
I'd recommend making public int
and string
overloads, but to prevent code duplication, internally call another method:
public static void ProcessObject(int x)
{
ProcessObject(GetObject(x));
}
public static void ProcessObject(string x)
{
ProcessObject(GetObject(x));
}
private static void ProcessObject(object o)
{
// do stuff with o
}
This makes your public
methods' input values clear: int
and string
are the only acceptable types, while still not duplicating your actual logic (// do stuff with o
).
You might dislike that the two public ProcessObject
methods are duplicates of each other, (on the surface anyway; under the hood, they're calling two different GetObject
overloads) but I think it's the best option.
Upvotes: 3
Reputation: 20720
Generally speaking, if your object reacts differently based on the generic type argument, you probably shouldn't be using generics in this case. Generics are great for situations where you want to do always the same thing, no matter what the actual type used.
Therefore, generic constraints will only allow you to list one base class for a type argument. Any actual types passed to the respective type arguments are meant to be a part of the given inheritance hierarchy starting with the base class you specified, so users of your class can specify any type that matches the base class or any of its subclasses.
At the same time, you, the author of the generic class, can safely assume that the specified type has (at least) the interface of the base class indicated by the constraint. Hence, you may access any members of the base class.
If you want to allow either string
or int
, imagine what members that could be. Both are derived directly from System.Object
, hence the restriction would make no sense as it is no restriction; every type is derived from System.Object
.
Summarizing, if you really want to treat string
and int
differently, this is definitely a case for offering two overloads rather than one generic class.
Upvotes: 1
Reputation: 726479
You cannot do what you are trying to do: first, it is not possible to list several classes in a generic constraint; second, the type that you can put in a constraint must be such that you could inherit it (or implement it if it is an interface). Both int
and string
fail this check. In cases like this, you would be better off with two separate overloads.
Upvotes: 2
Reputation: 4778
it's impossible in C# take a look on Constraints on Type Parameters. Try to use dynamic
Upvotes: 1
Reputation: 35895
Just remove the where
part
public static void ProcessObject<T>(T x)
{
object o = GetObject(x);
}
And also don't use object
in your other methods, instead use T
Upvotes: 1