Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/date/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在C#中有统一的调用Invoke()的方法吗?_C#_Func - Fatal编程技术网

在C#中有统一的调用Invoke()的方法吗?

在C#中有统一的调用Invoke()的方法吗?,c#,func,C#,Func,下面的测试通过了,但我想知道是否有可能进行统一的治疗。能做到吗 public abstract class MyInvokable<TResult> { public abstract TResult Invoke(); } public class IntInvokable: MyInvokable<int> { public override int Invoke() { return 12; } } [Test()] public void Fu

下面的测试通过了,但我想知道是否有可能进行统一的治疗。能做到吗

public abstract class MyInvokable<TResult> {
  public abstract TResult Invoke();
}
public class IntInvokable: MyInvokable<int> {
  public override int Invoke() {
    return 12;
  }
}
[Test()]
public void FunctionInvokeTest () {
  Func<int> foo = () => 6;
  IntInvokable bar = new IntInvokable();
  int six = foo.Invoke();
  int twelve = bar.Invoke();
  Assert.AreEqual(6, six);
  Assert.AreEqual(12, twelve);
  /* Now, what I really want to do but can't, as far as I can tell:
  List<SomeType> list = new List<SomeType>(){foo, bar};
  Assert.AreEqual(6, list[0].Invoke());
  Assert.AreEqual(12, list[1].Invoke()); */
}
公共抽象类MyInvokable{
公共抽象TResult Invoke();
}
公共类IntInvokable:MyInvokable{
公共覆盖int Invoke(){
返回12;
}
}
[测试()]
公共void函数invokeTest(){
Func foo=()=>6;
IntInvokable条=新的IntInvokable();
intsix=foo.Invoke();
int十二=bar.Invoke();
断言。相等(6,6);
主张平等(12,12);
/*现在,就我所知,我真正想做但不能做的是:
列表=新列表(){foo,bar};
Assert.AreEqual(6,列表[0].Invoke());
Assert.AreEqual(12,列表[1].Invoke())*/
}
编辑:已在以下位置向Microsoft启动功能请求:

C#不允许任何接近这种动态行为的行为

但是,如果您确实需要这样做,您可以始终使用
dynamic
,基本上是向编译器发出所有赌注都已结束的信号。这将有助于:

 List<dynamic> list = new List<dynamic>(){foo, bar};
 Assert.AreEqual(6, list[0].Invoke());
 Assert.AreEqual(12, list[1].Invoke());
public interface IInvokable
{
    int Invoke();
}

var l = new List<IInvokable>();
List List=newlist(){foo,bar};
Assert.AreEqual(6,列表[0].Invoke());
Assert.AreEqual(12,列表[1].Invoke());
但是,您不能以任何方式保证
列表
变量中的任何内容实际上都有一个
调用
方法

与此最相似的特性是TypeScript的结构接口——只要类型具有接口所需的所有方法/属性,就可以考虑实现接口。 在C#中,两个不同的事物可以被视为具有相似类型的唯一方法是,它们显式声明实现相同的接口,或继承相同的基类

如果能在C#中以某种方式拥有一个结构语义,那就太好了,但它甚至不在路线图上,好吧。

拥有一个
列表
,其中唯一需要的是
T
有一个无参数的
Invoke
方法,您需要将该需求烘焙到接口或基类中

因此,这两种方法中的任何一种都有效:

 List<dynamic> list = new List<dynamic>(){foo, bar};
 Assert.AreEqual(6, list[0].Invoke());
 Assert.AreEqual(12, list[1].Invoke());
public interface IInvokable
{
    int Invoke();
}

var l = new List<IInvokable>();
公共接口IInvokable
{
int Invoke();
}
var l=新列表();
或者这个:

public class Invokable
{
    public virtual int Invoke() { ... }
}

var l = new List<Invokable>();
公共类可调用
{
公共虚拟int Invoke(){…}
}
var l=新列表();
显然,现在需要在该类中包装委托,例如:

public class FuncInvokable : IInvokable
{
    private readonly Func<int> _Func;
    public FuncInvokable(Func<int> func) { _Func = func; }
    public int Invoke() { return _Func(); }
}
public类FuncInvokable:IInvokable
{
私有只读函数_Func;
公共FuncInvokable(Func Func){u Func=Func;}
公共int Invoke(){return_Func();}
}
或者。。。您可以将代理放置在列表中,并将所有对象包装在代理中:

var l = new List<Func<int>>();
l.Add(foo);
l.Add(() => bar.Invoke());
var l=新列表();
l、 添加(foo);
l、 添加(()=>bar.Invoke());
但无法定义这一点:

var l = new List<Type that has an Invoke method>();
var l=新列表();

我相当确定您无法真正实现这一点,但解释为什么是另一回事:dpobly类?为什么要使用不同的东西?如果它们都是相同的
类型
,您可以将它们存储在一个列表中。它们可能来自不同的源、模块等。这就是多态性的本质。是的,但是在面向对象编程中使用多态性,您也有一些共同的知识。这里唯一的常识是,在对象层次结构(复数)的某个地方有一个Invoke方法,这还不够好。您需要从一个公共基继承,或者实现一个公共接口,而所涉及的类型不能做到这一点。要真正拥有一个能够包含这些内容的数据结构,您需要将委托包装成某种东西,比如从
MyInvokable
派生的类。