在C#(3.0)中使用条件(?:)运算符进行方法选择?

我正在重构一些代码。

现在有很多地方有这样的function:

string error; if (a) { error = f1(a, long, parameter, list); } else { error = f2(the_same, long, parameter, list); } 

在重构f1和f2之前(虽然很大,但做类似的事情),我想重构为:

 string error = (a ? f1 : f2)(a, long, parameter, list); 

就像在C中一样。(函数签名是相同的)

但是我收到一个错误:

“错误13无法确定条件表达式的类型,因为’方法组’和’方法组’之间没有隐式转换”

这将允许我通过初始重构给出不变行为来识别参数列表是相同的,并且还在单个位置重构调用,确保在这些各种重构期间所有内容都没有被破坏,因为我将调用接口更改为方法。

我错过了一些小的东西,允许接近这个的语法工作(而不是一大堆额外的委托类型定义等)?

抱歉编辑,但实际上有一个返回值,是的,不幸的是,它是一个字符串。 ;-(

现在,我正在解决这个问题:

 string error = a ? f1(a, long, parameter, list) : f2(a, long, parameter, list); 

问题是参数列表确实很长,并且将被重构,我更愿意首先合并它们并在我更改时处理编译器错误。

正如你所指出的那样,你可以通过声明一个委托来做到这一点。

我注意到你写过你在很多地方这样做。 另一种可能更合适的替代方案是使用接口。 根据a的值实例化两种不同类型中的一种,然后在该对象上调用该方法。

 IFoo foo = a ? new Foo1() : new Foo2(); foo.f(a, long, parameter, list); 

如果您有多个方法需要根据a的值同时更改,那么您可以将它们全部包含在同一个界面中,您只需要测试一次。

对于? 为了工作,编译器需要至少一个操作数的显式类型。 您可以通过演员来提供一个

 (a ? (Action)f1 : f2)(a, long, parameter, list); 

T*替换为委托参数的实际类型

您必须将其中一个方法实例化为特定的兼容委托类型。 没有办法绕过它。 不幸的是,这将比你正在寻找的更冗长:

 (a ? new Action(f1) : f2)(a, long, parameter, list); 

您将不得不使参数显式化,无论是通过使用适合或声明您自己的委托类型的Action (或Func )generics重载。

这归结为类型分辨率。 鉴于表达式:

 condition ? tVal : fVal 

编译器不会为tValfVal寻找与通用的赋值兼容的祖先(并且,即使它确实如此,每个可能有效的不同委托类型的连续可能是巨大的 ); 如果在任一方向上tValfVal的类型之间没有赋值兼容性,编译器会使您明确表达您想要的内容。

对于它的价值,您应该知道,每次调用此方法时,采用此方法都会将新委托分配给f1f2 ,然后将调用该委托,然后将其丢弃。 我提出这个问题只是因为委托调用比普通的早期绑定(甚至虚拟)方法调用慢。 它可能不是一个考虑因素,权衡可能是值得的,但它仍然值得了解

如果您指定委托类型,它将允许您执行您要求的操作:

  (test ? (Action)M1 : M2)(10, 15) 

随着声明:

  void M1(int a, int b) { } void M2(int a, int b) { } 

测试.Net 4,但应该申请.Net 3.5

不,基本上,不会降低效率。 如果有返回值,您可以使用:

 var result = cond ? methodA(a,b,c,d) : methodB(a,b,c,d); 

但就是这样。

好吧,你可以从方法组创建一对委托,但这没有任何充分的理由增加了开销。 我不会认可它。

我认为以下内容会更好:

一个 ? f1(a,long,parameter,list):f2(a,long,parameter,list);

将三元组的结果转换为Action

 ((Action)(a ? f1 : f2))(int1, int2);