I would like to differentiate between following cases:
- A plain value type (e.g.
int
) - A nullable value type (e.g.
int?
) - A reference type (e.g.
string
) - optionally, I would not care if this mapped to (1) or (2) above
I have come up with the following code, which works fine for cases (1) and (2):
static void Foo<T>(T a) where T : struct { } // 1
static void Foo<T>(T? a) where T : struct { } // 2
However, if I try to detect case (3) like this, it does not compile:
static void Foo<T>(T a) where T : class { } // 3
The error message is Type 'X' already defines a member called 'Foo' with the same parameter types. Well, somehow I cannot make a difference between where T : struct
and where T : class
.
If I remove the third function (3), the following code does not compile either:
int x = 1;
int? y = 2;
string z = "a";
Foo (x); // OK, calls (1)
Foo (y); // OK, calls (2)
Foo (z); // error: the type 'string' must be a non-nullable value type ...
How can I get Foo(z)
to compile, mapping it to one of the above functions (or a third one with another constraint, which I have not thought of)?