And*_*are 14 c# compiler-construction anonymous-types
我想知道如何做这样的工作:
using System;
class Program
{
static void Main()
{
var f = new IFoo {
Foo = "foo",
Print = () => Console.WriteLine(Foo)
};
}
}
interface IFoo
{
String Foo { get; set; }
void Print();
}
Run Code Online (Sandbox Code Playgroud)
创建的匿名类型看起来像这样:
internal sealed class <>f__AnonymousType0<<Foo>j__TPar> : IFoo
{
readonly <Foo>j__TPar <Foo>i__Field;
public <>f__AnonymousType0(<Foo>j__TPar Foo)
{
this.<Foo>i__Field = Foo;
}
public <Foo>j__TPar Foo
{
get { return this.<Foo>i__Field; }
}
public void Print()
{
Console.WriteLine(this.Foo);
}
}
Run Code Online (Sandbox Code Playgroud)
是否有任何理由让编译器无法做到这样的事情?即使对于采用参数的非void方法或方法,编译器也应该能够从接口声明中推断出类型.
免责声明:虽然我确实认识到目前这不可行,但在这种情况下简单地创建一个具体的类更有意义,我对此的理论方面更感兴趣.
重载成员,索引器和显式接口实现会有一些问题.
但是,您可以以允许您解决这些问题的方式定义语法.
有趣的是,通过编写库,您可以非常接近C#3.0所需的内容.基本上,你可以这样做:
Create<IFoo>
(
new
{
Foo = "foo",
Print = (Action)(() => Console.WriteLine(Foo))
}
);
Run Code Online (Sandbox Code Playgroud)
这与你想要的非常接近.主要区别是调用"Create"而不是"new"关键字,以及需要指定委托类型的事实.
"创建"的声明如下所示:
T Create<T> (object o)
{
//...
}
Run Code Online (Sandbox Code Playgroud)
然后,它将使用Reflection.Emit在运行时动态生成接口实现.
但是,这种语法确实存在显式接口实现和重载成员的问题,在不更改编译器的情况下无法解决.
另一种方法是使用集合初始值设定项而不是匿名类型.这看起来像这样:
Create
{
new Members<IFoo>
{
{"Print", ((IFoo @this)=>Console.WriteLine(Foo))},
{"Foo", "foo"}
}
}
Run Code Online (Sandbox Code Playgroud)
这将使您能够:
你需要做一些事情来实现这个:
它需要c#4,但开源框架即兴接口可以在内部使用DLR代理来伪装这个开箱即用.虽然不如你提出的改变存在,但表现还是不错的.
using ImpromptuInterface.Dynamic;
Run Code Online (Sandbox Code Playgroud)
...
var f = ImpromptuGet.Create<IFoo>(new{
Foo = "foo",
Print = ReturnVoid.Arguments(() => Console.WriteLine(Foo))
});
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4495 次 |
| 最近记录: |