Reputation: 6609
I was trying understand a extension method to convert string
to Enum
found here.
public static T ToEnum<T>(this string value, T defaultValue)
{
if (string.IsNullOrEmpty(value))
{
return defaultValue;
}
T result;
return Enum.TryParse<T>(value, true, out result) ? result : defaultValue;
}
Compile Error:
The type 'T' must be a non-nullable value type in order to use it as parameter 'TEnum' in the generic type or method 'Enum.TryParse(string, bool, out TEnum)'
One the Comments says to add where T : struct
for the extension method to work.
Method With Constraint:
public static T ToEnum<T>(this string value, T defaultValue) where T : struct
{
if (string.IsNullOrEmpty(value))
{
return defaultValue;
}
T result;
return Enum.TryParse<T>(value, true, out result) ? result : defaultValue;
}
I read the docs on Enum.TryParse , but I don't understand in docs on why where T : struct
is added as constraint for type T ?
Why would above extension wont work without constraint as struct
why not other value types ? How to relate struct
and Enum
type ? or Is it just a syntax to follow ?
Update:
Most of them said any value type can be used , I tried to use where T : int
But I get compile time error:
'int' is not a valid constraint. A type used as a constraint must be an interface, a non-sealed class or a type parameter.
Upvotes: 2
Views: 1255
Reputation: 37000
The constraint struct
does not only include types you declared via struct MyStruct
, but also many built-in-types such as int
, byte
or char
. Actually the constraint restricts T
to be of any value-type, see this from the C#-specification 9.4.5 Satisfying constraints:
If the constraint is the value type constraint (struct), the type A shall satisfy one of the following
- A is a struct type or enum type, but not a nullable value type. [Note: System.ValueType and System.Enum are reference types that do not satisfy this constraint. end note]
- A is a type parameter having the value type constraint (§15.2.5)
Of course it´ll be nice if there were a more restricitve constraint.
As of your edit: your compiler-message is pretty clear in this case. When using a type as constraint, you can use only interfaces or non-sealed classed. Restricting a generic type-parameter to match exactly one single class (or struct) would make a generic quite useless, wouldn´t it? Restricting your generic to int
will effectivly turn your method-signature in something like this:
public static int ToEnum(this string value, int defaultValue)
because there´s only one struct matching the constraint.
Upvotes: 1
Reputation: 726579
This is done to enable partial error checking at compile time:
enum
s are rejected at runtime.It would be better if you could write where T : Enum
, but C# compiler prohibits this:
A constraint cannot be special class `System.Enum'
For more information on this error see this Q&A. In particular, see this answer for a short work-around to the problem.
Upvotes: 0