Преобразовать в IEnumerable <dynamic>?

Я написал этот метод расширения:

public static class A
{
 public static IEnumerable<dynamic> AsDynamic<T>(this IEnumerable<T> f)
    {
        foreach (var element in f)
        {
                yield return (dynamic) element;
        }   
    }
}

И протестировал его:

List<int> l   = new List<int>(){1,2,3};
Console.WriteLine ( l.AsDynamic().GetType());

Однако вывод: typeof (IEnumerable<Object>)

  • Почему это не typeof (IEnumerable<dynamic>)?

  • Как я могу заставить его быть таким?

Ответ 1

Я думаю, что у вас есть непонимание того, что означает dynamic. По сути, когда вы сообщаете компилятору, что тип объекта dynamic, вы "обещаете", что объект во время выполнения будет поддерживать любые методы или свойства, которые вы вызываете, в обмен на компилятор, не жалующийся во время компиляции. Вы также обещаете, что столкнетесь с последствиями, если нарушите свое обещание.

Когда вы говорите, что объект dynamic, компилятор не может делать предположения о типе, поэтому он использует object, зная, что что-либо можно сохранить как object. Когда вы делаете IEnumerable<dynamic>, он становится IEnumerable<object> с одним существенным различием: вы можете вызывать любой метод на своих элементах, а компилятор не произносит ни слова:

IEnumerable<SomeType> original = ...
foreach (dynamic x in original.AsDynamic()) { // Using your method
    Console.WriteLine(x.SomeUnsupportedMethod()); // The compiler is silent!
}

Так как original.AsDynamic() дает последовательность объектов dynamic, компилятор не жалуется на ваш вызов SomeUnsupportedMethod. Если этот метод действительно не поддерживается во время выполнения, программа выйдет из строя; если метод фактически поддерживается элементами SomeType, не было бы сбоя, и метод будет вызван.

Чтобы все dynamic сделало для вас; статически, "placeholder" останется object, а typeof расскажет вам столько же. Но точные возможности объекта (его методы и свойства) не будут проверяться до времени выполнения.

Ответ 2

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

Таким образом, тип выполнения будет typeof (IEnumerable<Object>)

Статический тип был бы typeof (IEnumerable<dynamic>)

Также

Среда выполнения рассматривает это истинно концептуально

typeof(object)==typeof(dynamic)

Итак,

Динамический тип подобен объекту, за исключением того, что он позволяет использовать способами, которые неизвестны во время компиляции.

Ответ 3

Попробуйте метод Linq Extension Cast(). Но я не уверен, что он будет работать с динамикой.

Ответ 4

Потому что dynamic не является типом

Console.WriteLine(typeof(dynamic)); // error

динамический решает только фактический тип во время выполнения