检测IEnumerable<;T>;已分组,I';我在检查类型时得到了一些疯狂的结果

本文关键字:类型 检查 结果 疯狂 gt lt IEnumerable 检测 | 更新日期: 2023-09-27 18:22:31

所以我试图弄清楚传递给我的方法的一些随机IEnumerable是否已经分组。我的想法是,我将以不同的方式处理分组数据。我的问题是IGrouping<>是一个通用接口,它没有实现非通用接口,无论出于什么原因,我都无法用is语句测试它。

在这里测试这是我的示例代码:

        var dict = new Dictionary<int, string>() {
            {1, "Prime" },
            {2, "Prime" },
            {3, "Prime" },
            {4, "Not" },
            {5, "Prime" },
            {6, "Not" },
            {7, "Prime" },
            {8, "Not" },
            {9, "Not" },
            {10, "Not" },
            {11, "Prime" }
        };
        var grouped = from d in dict
                      group d by d.Value into gd
                      select gd;
        Debug.WriteLine("IEnumerable<IGrouping<string, KeyValuePair<int, string>>>: {0}", grouped is IEnumerable<IGrouping<string, KeyValuePair<int, string>>>);
        Debug.WriteLine("IEnumerable<IGrouping<object, KeyValuePair<int, string>>>: {0}", grouped is IEnumerable<IGrouping<object, KeyValuePair<int, string>>>);
        Debug.WriteLine("IEnumerable<IGrouping<object, KeyValuePair<object, object>>: {0}", grouped is IEnumerable<IGrouping<object, object>>);
        Debug.WriteLine("IEnumerable<IGrouping<object, object>: {0}", grouped is IEnumerable<IGrouping<object, object>>);
        Debug.WriteLine("IEnumerable<object>: {0}", grouped is IEnumerable<object>);

输出如下:

IEnumerable<IGrouping<string, KeyValuePair<int, string>>>: True
IEnumerable<IGrouping<object, KeyValuePair<int, string>>>: True
IEnumerable<IGrouping<object, KeyValuePair<object, object>>: False
IEnumerable<IGrouping<object, object>: False
IEnumerable<object>: True

所以,除非我知道要分组的值的类型,否则我无法测试它是否分组了?这是.Net Framework中的错误吗?

上面的结果怎么可能呢?


编辑:Jon Skeet的回答完全正确……作为对其他发现自己在这里遇到同样困难的人的礼貌,以下代码完成了检查IEnumerable是否分组的工作(基于Skeet先生使用动态关键字的绝妙想法):

    public static bool IsGrouped (dynamic test) {
        return CheckGrouping(test);
    }
    static bool CheckGrouping(object o ) {
        return false;
    }
    static bool CheckGrouping<TKey, TValue>(IEnumerable<IGrouping<TKey, TValue>> grouping) {
        return true;
    }

假设代码与上面相同:

IsGrouped(dict); //false
IsGrouped(grouped); //true

检测IEnumerable<;T>;已分组,I';我在检查类型时得到了一些疯狂的结果

在.NET 4下,结果不仅是可能的,而且是预期的-在.NET 3.5中,由于缺乏通用方差,最终结果将为False。

虽然IGrouping<out TKey, out TValue>TKeyTValue中都是协变的,但KeyValuePair<Tkey, TValue>是一个结构,因此不能以协变的方式使用。

所以IGrouping<string, string>IGrouping<object, object>,但IGrouping<string, KeyValuePair<int, string>>不是。

这不是框架中的错误。至于如何找出某个TKey, TValue对是否实现了IGrouping<TKey, TValue>,您可以自己努力工作,也可以使用dynamic来尝试帮助:

// Code as before...
dynamic dyn = grouped;
ShowGrouping(dyn);
private static void ShowGrouping<TKey, TValue>
   (IEnumerable<IGrouping<TKey, TValue>> grouping)
{
    Console.WriteLine("TKey = {0}, TValue = {1}", typeof(TKey), typeof(TValue));
}
private static void ShowGrouping(object notGrouped)
{
    Console.WriteLine("Not a grouping");
}

请注意,这当然不是万无一失的,但它可能足以满足您的需求。