В дополнение к вашему комментарию к ответу Marnix вы можете добиться того, чего хотите, используя немного отражения.
В приведенном ниже примере метод неограниченного использования Foo
использует отражение для обработки вызовов на соответствующий ограниченный метод - либо FooWithStruct
, либо FooWithClass
. По соображениям производительности мы будем создавать и кэшировать строго типизированный делегат, а не использовать обычное отражение каждый раз, когда вызывается метод Foo
.
int x = 42;
MyClass.Foo(x); // displays "Non-Nullable Struct"
int? y = 123;
MyClass.Foo(y); // displays "Nullable Struct"
string z = "Test";
MyClass.Foo(z); // displays "Class"
// ...
public static class MyClass
{
public static void Foo(T? a) where T : struct
{
Console.WriteLine("Nullable Struct");
}
public static void Foo(T a)
{
Type t = typeof(T);
Delegate action;
if (!FooDelegateCache.TryGetValue(t, out action))
{
MethodInfo mi = t.IsValueType ? FooWithStructInfo : FooWithClassInfo;
action = Delegate.CreateDelegate(typeof(Action), mi.MakeGenericMethod(t));
FooDelegateCache.Add(t, action);
}
((Action)action)(a);
}
private static void FooWithStruct(T a) where T : struct
{
Console.WriteLine("Non-Nullable Struct");
}
private static void FooWithClass(T a) where T : class
{
Console.WriteLine("Class");
}
private static readonly MethodInfo FooWithStructInfo = typeof(MyClass).GetMethod("FooWithStruct", BindingFlags.NonPublic | BindingFlags.Static);
private static readonly MethodInfo FooWithClassInfo = typeof(MyClass).GetMethod("FooWithClass", BindingFlags.NonPublic | BindingFlags.Static);
private static readonly Dictionary FooDelegateCache = new Dictionary();
}
(Обратите внимание, что этот пример не является потоковым .Если вам нужна безопасность потоков, вам придется либо использовать какую-то блокировку во всем доступе к кеш-словарю, либо - если вы можете настроить таргетинг на .NET4 - используйте ConcurrentDictionary
.)