考虑以下代码:
public static class TypeChecker
{
public static string CheckType<T>()
{
return typeof(T).IsValueType ? HandleValueType<T>() : HandleReferenceType<T>();
}
/*
compilatioon error looks like this:
1>Pure.cs(9,44): Error CS0453 : The type 'T' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'TypeChecker.HandleValueType<T>()'
1>Pure.cs(9,67): Error CS0452 : The type 'T' must be a reference type in order to use it as parameter 'T' in the generic type or method 'TypeChecker.HandleReferenceType<T>()'
*/
private static string HandleValueType<T>() where T : struct
{
return $"This is a value type (struct): {typeof(T).Name}";
}
private static string HandleReferenceType<T>() where T : class
{
return $"This is a reference type: {typeof(T).Name}";
}
}
编译器无法将
typeof
与 2 个私有函数施加的约束关联起来,这解释了错误。最简单的方法是什么?
我正在使用 C# 9.x,但更高版本的解决方案也将受到赞赏
您可以使用静态泛型类、其中的字段和表达式树来施展一些魔法:
public static class TypeChecker
{
private static class TypeCheckerInternal<T>
{
private static Func<string> _handle;
static TypeCheckerInternal()
{
var handleReferenceType = typeof(TypeChecker)
.GetMethod(nameof(TypeChecker.HandleReferenceType), BindingFlags.Static | BindingFlags.NonPublic);
var handleValueType = typeof(TypeChecker)
.GetMethod(nameof(TypeChecker.HandleValueType), BindingFlags.Static | BindingFlags.NonPublic);
var method = typeof(T).IsValueType
? handleValueType.MakeGenericMethod(typeof(T))
: handleReferenceType.MakeGenericMethod(typeof(T));
var expression = Expression.Lambda<Func<string>>(Expression.Call(method));
_handle = expression.Compile();
}
public static string Handle() => _handle();
}
public static string CheckType<T>()
{
return TypeCheckerInternal<T>.Handle();
}
private static string HandleValueType<T>() where T : struct
{
return $"This is a value type (struct): {typeof(T).Name}";
}
private static string HandleReferenceType<T>() where T : class
{
return $"This is a reference type: {typeof(T).Name}";
}
}