简体   繁体   English

在C#中检查泛型方法的类型参数

[英]Checking type parameter of a generic method in C#

Is it possible to do something like this in C#: 是否有可能在C#中做这样的事情:

public void DoSomething<T>(T t)  
{
    if (T is MyClass)
    {
        MyClass mc = (MyClass)t 
        ...
    }
    else if (T is List<MyClass>)
    {
        List<MyClass> lmc = (List<MyClass>)t
        ...
    }
}

Yes: 是:

if (typeof(T) == typeof(MyClass))
{
    MyClass mc = (MyClass)(object) t;
}
else if (typeof(T) == typeof(List<MyClass>))
{
    List<MyClass> lmc = (List<MyClass>)(object) t;
}

It's slightly odd that you need to go via a cast to object, but that's just the way that generics work - there aren't as many conversions from a generic type as you might expect. 您需要通过强制转换为对象,这有点奇怪,但这只是泛型工作的方式 - 没有像您预期的那样从泛型类型转换。

Of course another alternative is to use the normal execution time check: 当然另一种选择是使用正常的执行时间检查:

MyClass mc = t as MyClass;
if (mc != null)
{
    // ...
}
else
{
    List<MyClass> lmc = t as List<MyClass>;
    if (lmc != null)
    {
        // ...
    }
}

That will behave differently to the first code block if t is null, of course. 当然,如果t为null,那将与第一个代码块的行为不同。

I would try to avoid this kind of code where possible, however - it can be necessary sometimes, but the idea of generic methods is to be able to write generic code which works the same way for any type. 我会尽可能地避免使用这种代码 - 但有时候它可能是必要的,但泛型方法的想法是能够编写对任何类型都以相同方式工作的通用代码。

It's 2017 and we have now C# 7 with pattern matching. 现在是2017年,我们现在拥有模式匹配的C#7。 If your type T inherit object you can you code like this 如果您的类型T继承object您可以像这样编码

void Main()
{
    DoSomething(new MyClass { a = 5 });
    DoSomething(new List<MyClass> { new MyClass { a = 5 }, new MyClass { a = 5 }});
}


public void DoSomething(object t)
{
    switch (t)
    {
        case MyClass c:
            Console.WriteLine($"class.a = {c.a}");
            break;
        case List<MyClass> l:
            Console.WriteLine($"list.count = {l.Count}");
            break;
    }
}

class MyClass
{
    public int a { get; set;}
}

Starting with C# 7, you can do this in a concise way with the is operator: 从C#7开始,您可以使用is运算符以简洁的方式执行此操作:

public void DoSomething<T>(T value)  
{
    if (value is MyClass mc)
    {
        ...
    }
    else if (value is List<MyClass> lmc)
    {
        ...
    }
}

See documentation: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/is#pattern-matching-with-is 请参阅文档: https//docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/is#pattern-matching-with-is

I believe there's something wrong in your design. 我相信你的设计有问题。 You want to compare between types in an already generic method. 您想要在已经通用的方法中比较类型。 Generics are meant to deal with type-variable situation. 泛型用于处理类型变量情况。 I recommend to do it this way.. 我建议这样做..

//Generic Overload 1
public void DoSomething<T>(T t)
    where T : MyClass
{
    ...
}

//Generic Overload 2
public void DoSomething<T>(T t)
    where T : List<MyClass>
{
    ...
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 具有该类型参数的C#通用方法对该参数没有属性 - C# Generic Method with a Parameter of that Type has no Properties on the Parameter C#-在通用方法中使用运行时定义的类型作为参数 - C# - Use runtime-defined type as parameter in generic method C#通用类型作为参数 - C# Generic Type as parameter 如何在c#中指定通用列表类型扩展方法的参数 - How to specify parameter for generic list type extension method in c# C# - Generic按参数返回类型的方法 - C# - Generic Method to return type according parameter 在c#中将泛型作为泛型类型参数传递 - Passing a generic as generic type parameter in c# 是否可以将C#泛型方法类型参数约束为“可从”包含类的类型参数“赋值”? - Is it possible to constrain a C# generic method type parameter as “assignable from” the containing class' type parameter? C# 泛型约束:class 上的类型参数继承方法上的类型参数? - C# generic constraint: type parameter on the class inherits type parameter on the method? C#类型推断泛型方法类型参数,其中方法没有参数 - C# type inference of a generic method type parameter where the method has no arguments c#reflectin:为给定的类实例调用具有泛型类型和泛型参数的方法 - c# reflectin: calling method with generic type and generic parameter for given instance of class
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM