首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >构造函数作为委托-在C#中可能吗?

构造函数作为委托-在C#中可能吗?
EN

Stack Overflow用户
提问于 2009-10-21 21:04:52
回答 9查看 24K关注 0票数 65

我有一个如下所示的类:

代码语言:javascript
复制
class Foo
{
  public Foo(int x) { ... }
}

我需要将一个委托传递给某个方法,如下所示:

代码语言:javascript
复制
delegate Foo FooGenerator(int x);

是否可以直接将构造函数作为FooGenerator值传递,而不必键入:

代码语言:javascript
复制
delegate(int x) { return new Foo(x); }

编辑:供我个人使用,这个问题涉及到.NET 2.0,但也欢迎针对3.0+的提示/回复。

EN

回答 9

Stack Overflow用户

回答已采纳

发布于 2009-10-21 21:15:23

不,CLR不允许将委托绑定到ConstructorInfo

但是,您可以只创建自己的:

代码语言:javascript
复制
static T Make<T>(Action<T> init) where T : new()
{
  var t = new T();
  init(t);
  return t;
}

用法

代码语言:javascript
复制
var t = Make<Foo>( x => { x.Bar = "bar"; x.Baz = 1; });
票数 37
EN

Stack Overflow用户

发布于 2009-10-21 23:35:23

我假设您通常会在工厂实现中执行类似的操作,其中实际类型在编译时是未知的……

首先,请注意,更简单的方法可能是创建后初始化步骤,然后您可以使用泛型:

代码语言:javascript
复制
static T Create<T>({args}) where T : class, ISomeInitInterface, new() {
    T t = new T();
    t.Init(args);
    return t;
}

然后,您可以使用MakeGenericMethod和/或CreateDelegate

否则,您可以使用Expression (3.5)或DynamicMethod (2.0)即时完成此操作。

Expression方法更易于编码:

代码语言:javascript
复制
    var param = Expression.Parameter(typeof(int), "val");
    var ctor = typeof(Foo).GetConstructor(new[] { typeof(int) });
    var lambda = Expression.Lambda<Func<int, Foo>>(
        Expression.New(ctor, param), param);
    var func = lambda.Compile();
    Foo foo = func(123);
    string s = foo.ToString(); // proof

或者(使用DynamicMethod):

代码语言:javascript
复制
    ConstructorInfo ctor = typeof(Foo).GetConstructor(new[] { typeof(int) });
    DynamicMethod dm = new DynamicMethod("Create", typeof(Foo),
            new Type[] { typeof(int) }, typeof(Foo), true);
    ILGenerator il = dm.GetILGenerator();
    il.Emit(OpCodes.Ldarg_0);
    il.Emit(OpCodes.Newobj, ctor);
    il.Emit(OpCodes.Ret);
    Converter<int, Foo> func = (Converter<int, Foo>)
        dm.CreateDelegate(typeof(Converter<int, Foo>));        
    Foo foo = func(123);
    string s = foo.ToString(); // proof
票数 60
EN

Stack Overflow用户

发布于 2009-10-21 21:15:23

我认为最简洁的(不需要转移到工厂模式)就是使用匿名方法,如下所示:

代码语言:javascript
复制
delegate Foo FooGenerator(int x);

...    

void DoStuff()
{
    YourDelegateConsumer(x => new Foo(x));
}

这并没有严格按照您的要求(因为您将委托传递给一个返回新实例的匿名方法,而不是直接委托给构造函数),但我认为您所要求的严格来说是不可能的。

当然,假设您使用的是3.5+

票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1600712

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档