6

我并不是指将较低的接口或基类转换为更派生的类的意义上的动态转换,我的意思是采用我创建的接口定义,然后动态地向该接口转换不是从该接口派生的不同对象接口但支持所有调用。

例如,

interface IMyInterface
{
   bool Visible
   {
      get;
   }
}

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

对于已知类型,这可以在编译时实现,对于使用动态声明的实例,可以在运行时实现。接口定义是已知的,类型也是已知的(在本例中),因此编译器可以确定对象是否支持接口定义的调用,并为我们执行一些魔术来进行强制转换。

我的猜测是这在 C#4 中不受支持(我无法找到对它的引用),但我想确定。如果不是,我想讨论它是否应该包含在语言的未来变体中,以及支持和反对的原因。对我来说,这似乎是一个很好的补充,可以在代码中实现更大的多态性,而无需创建全新的类型来包装现有的框架类型。

更新
以免有人指责我抄袭,我不知道Jon Skeet 已经提出了这个。然而,很高兴知道我们想到了非常相似的语法,这表明它至少可能是直观的。与此同时,“有一个原创的想法”在我的遗愿清单上又保留了一天。

4

4 回答 4

3

我认为 Jon Skeet 有过这样的提议(http://msmvps.com/blogs/jon_skeet/archive/2008/10/30/c-4-0-dynamic-lt-t-gt.aspx),但到目前为止,我还没有听说 C# 4.0 会有它。

于 2009-04-30T18:34:09.490 回答
3

我认为这是有问题的。您正在引入两个未耦合的类之间的耦合。

考虑以下代码。

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 表面上不相关,您的代码也会再次中断。

事实是,尽管这在您无法控制的对象之间存在相似性的特定情况下很有用,但接口必须显式附加到对象是有原因的,原因是编译器可以保证对象实现它。

于 2009-04-30T18:46:40.397 回答
1

C# 不需要支持这一点,因为它可以作为库非常干净地实现。

我见过三四个独立的实现(我在找到它们之前就开始自己写一个)。这是我见过的最彻底的治疗:

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

一旦将 DLR 集成到运行时中,它可能会更容易实现。

因为给定接口的wrapper/forwarder类可以生成一次然后缓存,然后给定类型未知的对象可以封装一次,调用站点等缓存的空间很大,所以性能应该是优秀的。

相比之下,我认为dynamic关键字是一种语言特征,而且是一个非常复杂的关键字,它是一种不必要且可能是灾难性的题外话,被硬塞进了一种以前有非常清晰的静态类型哲学的语言中,这给了它一个明显的方向以供将来改进。他们应该坚持这一点,让类型推断工作得越来越好,直到打字变得更加不可见。有很多领域他们可以在不破坏现有程序的情况下发展语言,但他们没有这样做,仅仅是由于资源限制(例如,var不能在更多地方使用的原因是因为他们必须重写编译器他们没有时间)。

他们仍然在 C# 4.0(方差特性)中做得很好,但还有很多其他工作要做,以使类型系统更智能、更自动化、更强大地在编译时检测问题。相反,我们本质上是在玩噱头。

于 2009-05-09T21:07:12.343 回答
1

开源框架Impromptu-Interface使用 C# 4 和 dlr 执行此操作。

using ImpromptuInterface;

interface IMyInterface
{
   bool Visible
   {
      get;
   }
}

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

由于它使用 dlr,因此它也适用于 ExpandoObject 和 DynamicObject。

于 2011-02-28T18:25:23.350 回答