Обнаружив, если IEnumerable <T>сгруппирован, я получаю некоторые сумасшедшие результаты при проверке типов - PullRequest
4 голосов
/ 03 февраля 2012

Итак, я пытаюсь выяснить, были ли сгруппированы какие-либо случайные 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?

Как вообще возможны результаты, приведенные выше?


РЕДАКТИРОВАТЬ: Ответ Джона Скита был мертв на ... Вежливостьвсем, кто оказался здесь с той же трудностью, что и я, следующий код проверил, чтобы проверить, сгруппирован ли IEnumerable или нет (основываясь на причудливой идее мистера Скита об использовании динамического ключевого слова):

    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

1 Ответ

10 голосов
/ 03 февраля 2012

Результаты не просто возможны, но ожидаются в .NET 4 - в .NET 3.5 конечный результат будет False из-за отсутствия общей дисперсии.

Хотя IGrouping<out TKey, out TValue> является ковариантным в TKey и TValue, KeyValuePair<Tkey, TValue> является структурой и поэтому не может использоваться ковариантным образом.

То есть IGrouping<string, string> - это IGrouping<object, object>, а IGrouping<string, KeyValuePair<int, string>> - нет.

Это не ошибка в фреймворке. Что касается того, как выяснить, реализует ли что-то IGrouping<TKey, TValue> для некоторой пары 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");
}

Обратите внимание, что это, конечно, не является надежным - но может быть достаточно для того, что вам нужно.

...