Может ли «динамический» тип безопасно изменяться в общей коллекции <dynamic>? - PullRequest
10 голосов
/ 01 февраля 2010

Основываясь на моем ответе на этот вопрос , я хочу проверить кое-что на моем понимании предстоящего типа dynamic для C # 4.

В этом случае у нас есть коллекция, которая представляет поля в записи, извлеченной из неизвестной таблицы базы данных. Более старый код (до .Net 4) требует, чтобы такая коллекция содержала элементы типа Object. Помимо достоинств такой коллекции, мне интересно, что происходит, когда вы меняете Object на dynamic.

С одной стороны, я ожидаю, что, поскольку все для динамических типов все прорабатывается во время выполнения, все должно быть хорошо, если программист не делает опечаток или ошибок относительно ожидаемого типа определенного элемента Коллекция.

С другой стороны, мне интересно слово "все" в предыдущем предложении. Может ли среда выполнения кешировать результаты при первом обращении к динамическому свойству, что приведет к сбою последующих вызовов с использованием различных типов?

Ответы [ 4 ]

3 голосов
/ 01 февраля 2010

Вот соответствующий фрагмент из блога Сэма, в котором кратко говорится о политике кэширования.

http://blogs.msdn.com/samng/archive/2008/10/29/dynamic-in-c.aspx

DLR проверяет кэш, чтобы увидеть, данное действие уже связано против текущего набора аргументов. Так что в нашем примере мы бы сделали тип совпадение на основе 1, 2 и времени выполнения тип г. Если у нас есть попадание в кеш, тогда мы возвращаем кешированный результат. Если у нас нет попадания в кеш, тогда DLR проверяет, является ли получатель объект IDynamicObject. Эти ребята по существу объекты, которые знают, как позаботиться о собственной привязке, такой как объекты COM IDispatch, реальные динамические объекты типа Ruby или Python, или некоторый объект .NET, который реализует интерфейс IDynamicObject. Если это любой из них, то DLR отменяет в IDO и просит его связать действие.

Обратите внимание, что результат вызова IDO для привязки - это дерево выражений, которое представляет результат привязки. Если это не IDO, то DLR звонки в языковой переплет (в нашем случай, связыватель времени выполнения C #), чтобы связать операция. Среда выполнения C # свяжет действие и вернется дерево выражений, представляющее результат привязки. Один шаг 2 или 3 произошло, в результате дерево выражений объединено в механизм кеширования, так что любой последующие вызовы могут работать против кеш вместо отскока.

Однако Сэм не упоминает, что именно это такое. Существуют две основные политики пропуска кэша: (1) запуск пропуска кэша при изменении типов аргументов, (2) запуск пропуска кэша при изменении идентификаторов аргументов.

Очевидно, что первый гораздо более производительный; Работать, когда мы можем кешировать данные только на основе типов, сложно. Детальное объяснение того, как работает вся эта логика, займет довольно много времени; надеюсь, я или Крис или Сэм сделаем запись в блоге об этом на днях.

1 голос
/ 01 февраля 2010

Вы можете думать о динамике как о синтаксическом сахаре для написания всех вызовов методов с использованием Reflection и MethodInfo.Invoke () - под капотом это работает не совсем так, но вы можете думать о том, как это работает со всеми соображениями «вызова 1000 методов / сек. через динамический => убитый перф», которые сопровождают это.

1 голос
/ 01 февраля 2010

Что касается словаря / , список , он может просто видеть object. dynamic в значительной степени в глазах смотрящего - то есть код , вызывающий ; под капотом это «объект плюс немного сахара». Так что проблем здесь не должно быть.

Доказательство:

    static void Main()
    {
        Console.WriteLine(IsObject<int>()); // false
        Console.WriteLine(IsObject<object>()); // true
        Console.WriteLine(IsObject<dynamic>()); // true
        Console.WriteLine(IsObject<string>()); // false
    }
    static bool IsObject<T>()
    {
        return typeof(T) == typeof(object);
    }
1 голос
/ 01 февраля 2010

Хорошо, вместо того, чтобы ждать ответа, я запустил Visual Studio 2010 beta 2, и эта тестовая программа работает нормально:

class Foo
{
    public string foo = "Foo!";
}
class Bar
{
    public int bar = 42;
}

class Program
{
    static void Main(string[] args)
    {
        var test = new List<dynamic>();
        test.Add(new Foo());
        test.Add(new Bar());

        Console.WriteLine(test[0].foo.Substring(0,3));
        Console.WriteLine(test[1].bar.ToString("000"));

        Console.ReadKey(true);
    }
}

Я хотел убедиться, что я не только проверял свойства с разными именами, но и имел разные типы, а также использовал в каждом типе функции, которые несовместимы друг с другом. Это , кажется, предполагает, что , если что-либо кэшируется, среда выполнения достаточно умна, чтобы знать, когда использовать кэш, а когда нет. Я все еще хотел бы услышать, знает ли кто-нибудь крайний случай, когда это не может иметь место, или более авторитетный комментарий, почему это будет.

...