如何有条件地调用具有约束的泛型方法? [英] How to conditionally invoke a generic method with constraints?

查看:42
本文介绍了如何有条件地调用具有约束的泛型方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一个不受约束的通用方法,该方法适用于所有支持相等性的类型.它执行成对相等性检查,因此可以在 O(n 2 )中工作:

Suppose I have an unconstrained generic method that works on all types supporting equality. It performs pairwise equality checks and so works in O(n2):

public static int CountDuplicates<T>(IList<T> list) 
{
    /* ... */ 
}

我还有一个受约束的通用方法,该方法仅适用于支持排序的类型.它从对 O(n log n)中的列表进行排序开始,然后一遍计算所有重复项:

I also have a constrained generic method that only works with types supporting sorting. It starts from sorting the list in O(n log n), and then counts all duplicates in one pass:

public static int CountDuplicatesFast<T>(IList<T> list) 
    where T : IComparable<T> 
{
    /* ... */ 
}

因此,如果从静态上知道列表元素的类型支持排序,则调用者可以选择调用快速方法.调用者本身可能会使用通用的 IList< T> 进行操作,其中T是不受约束的,因此它是调用第一个(慢速)方法的唯一选择.

So, a caller can choose to invoke the fast method if it is statically known that the type of elements of the list supports ordering. It might happen that the caller itself works with generic IList<T> where T is unconstrained, so its only option to invoke the first (slow) method.

现在,我希望第一种方法在运行时检查类型 T 是否实际实现了接口 IComparable< T> ,如果是,请调用快速方法:

Now, I want the first method to check at runtime if the type T actually implements the interface IComparable<T> and if so, invoke the fast method:

public static int CountDuplicates<T>(IList<T> list)
{
    if (typeof(IComparable<T>).IsAssignableFrom(typeof(T)))
    {
        return CountDuplicatesFast(list);
    }
    else
    {
        /* use the slow algorithm */
    }
}

问题是编译器拒绝调用 CountDuplicatesFast(list):

The problem is the compiler rejects the invocation CountDuplicatesFast(list):

错误CS0314:类型'T'不能用作通用类型或方法'Program.CountDuplicatesFast< T>(System.Collections.Generic.IList< T>)'中的类型参数'T'.没有从"T"到"System.IComparable< T>"的装箱转换或类型参数转换.

是否可以说服编译器相信我知道自己在做什么,而跳过约束检查?

Is it possible to persuade the compiler to trust me that I know what I am doing, and to skip the constraint check?

推荐答案

这是使用 dynamic :

if (typeof(IComparable<T>).IsAssignableFrom(typeof(T)))
{
    return CountDuplicatesFast((dynamic)list);
}

或带有反射:

if (typeof(IComparable<T>).IsAssignableFrom(typeof(T)))
{
    var method = typeof(MyType).GetMethod("CountDuplicatesFast");
    var generic = method.MakeGenericMethod(typeof(T));
    return (int)generic.Invoke(null, new object[] { list });
}

我不认为有一种方法可以静态地执行此操作(即,无需反射或 dynamic ).

I don't think that there's a way to do this statically (i.e. without reflection or dynamic).

这篇关于如何有条件地调用具有约束的泛型方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆