Позволит ли C # 4 “динамическое приведение”?Если нет, должен ли C # поддерживать это?

StackOverflow https://stackoverflow.com/questions/808384

Вопрос

Я не имею в виду динамическое приведение в смысле приведения более низкого интерфейса или базового класса к более производному классу, я имею в виду принятие определения интерфейса, которое я создал, а затем динамическое приведение к этому интерфейсу другого объекта, НЕ производного от этого интерфейса, но поддерживающего все вызовы.

Например,

interface IMyInterface
{
   bool Visible
   {
      get;
   }
}

TextBox myTextBox = new TextBox();
IMyInterface i = (dynamic<IMyInterface>)myTextBox;

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

Я предполагаю, что это не поддерживается в C # 4 (я не смог найти ссылку на это), но я хотел бы знать наверняка.И если это не так, я хотел бы обсудить, следует ли это включать в будущий вариант языка или нет, а также причины "за" и "против".Мне это кажется приятным дополнением для обеспечения большего полиморфизма в коде без необходимости создавать совершенно новые типы для переноса существующих типов фреймворка.

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

Это было полезно?

Решение

Я думаю , что у Джона Скита было такое предложение (http://msmvps.com/blogs/jon_skeet/archive/2008/10/30/c-4-0-dynamic-lt-t-gt.aspx), но пока я не слышал, что в C # 4.0 это будет.

Другие советы

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

Рассмотрим следующий код.

public interface IFoo
{
   int MethodA();
   int MethodB();
}

public class Bar
{
   int MethodA();
   int MethodB();
}

public class SomeClass
{
   int MethodFoo(IFoo someFoo);
}

должно ли это тогда быть законным?

int blah = someClass.MethodFoo((dynamic<IFoo>)bar);

IT кажется как будто это должно быть законно, потому что компилятор должен иметь возможность динамически вводить bar как нечто, реализующее IFoo.

Однако на данном этапе вы связываете IFoo и Bar посредством вызова в совершенно отдельной части вашего кода.

Если вы отредактируете Bar, потому что ему больше не нужен methodB, внезапно SomeClass.MethodFood больше не работает, хотя Bar и IFoo не связаны.

Точно так же, если вы добавите MethodC() в IFoo, ваш код снова сломается, даже если IFoo и Bar якобы не связаны.

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

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

Я видел три или четыре отдельные реализации (я начал писать одну сам, прежде чем нашел их).Вот самое тщательное лечение, которое я когда-либо видел:

http://bartdesmet.net/blogs/bart/archive/2008/11/10/introducing-the-c-ducktaper-bridging-the-dynamic-world-with-the-static-world.aspx

Вероятно, это будет еще проще реализовать, как только DLR будет интегрирован в среду выполнения.

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

Напротив, я думаю, что dynamic ключевое слово, являющееся особенностью языка, причем чрезвычайно сложной, является ненужным и потенциально катастрофическим отступлением от языка, который ранее имел очень четкую философию статической типизации, что дало ему очевидное направление для дальнейшего совершенствования.Они должны были придерживаться этого и заставлять вывод типов работать все лучше и лучше, пока набор текста не станет более незаметным.Существует так много областей, где они могли бы развивать язык, не нарушая работу существующих программ, и все же они этого не делают просто из-за нехватки ресурсов (напримерпричина var не могут быть использованы в большем количестве мест, потому что им пришлось бы переписать компилятор, а у них нет времени).

Они все еще делают хорошие вещи в C # 4.0 (функции variance), но есть так много другого, что можно было бы сделать, чтобы сделать систему типов более умной, более автоматической, более мощной при обнаружении проблем во время компиляции.Вместо этого мы, по сути, получаем трюк.

Фреймворк с открытым исходным кодом Импровизированный интерфейс делает это с помощью C # 4 и dlr.

using ImpromptuInterface;

interface IMyInterface
{
   bool Visible
   {
      get;
   }
}

TextBox myTextBox = new TextBox();
IMyInterface i = myTextBox.ActLike<IMyInterface>();

Поскольку он использует dlr, он также будет работать с ExpandoObject и DynamicObject.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top