Позволит ли C # 4 "динамическое приведение"? Если нет, должен ли C # это поддерживать? - PullRequest
6 голосов
/ 30 апреля 2009

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

Например,

interface IMyInterface
{
   bool Visible
   {
      get;
   }
}

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

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

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

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

Ответы [ 4 ]

3 голосов
/ 30 апреля 2009

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

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

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);

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

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

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

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

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

3 голосов
/ 30 апреля 2009

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

1 голос
/ 28 февраля 2011

Фреймворк с открытым исходным кодом Impromptu-Interface делает это, используя C # 4 и dlr.

using ImpromptuInterface;

interface IMyInterface
{
   bool Visible
   {
      get;
   }
}

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

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

1 голос
/ 10 мая 2009

Нет необходимости в 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 (функции отклонения), но есть еще много всего, что можно сделать, чтобы сделать систему типов умнее, более автоматической, более мощной при обнаружении проблем во время компиляции. Вместо этого мы получаем трюк.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...