在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
派生的类。