Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.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#(3.0)中使用条件(?:)运算符进行方法选择?_C#_.net_.net 3.5 - Fatal编程技术网

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

在C#(3.0)中使用条件(?:)运算符进行方法选择?,c#,.net,.net-3.5,C#,.net,.net 3.5,我正在重构一些代码 现在有很多地方有这样的功能: 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中一样。(函数签

我正在重构一些代码

现在有很多地方有这样的功能:

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 ? new Action<T1, T2, T3, T4>(f1) : f2)(a, long, parameter, list);
编译器不会为
tVal
fVal
寻找通用的与赋值兼容的祖先(而且,即使这样做了,每种类型都可能有效的不同委托类型可能会非常多);如果
tVal
fVal
的两种类型在两个方向上都不兼容赋值,编译器会让您明确自己想要什么


值得一提的是,您应该知道,采用这种方法会在每次调用此方法时将一个新委托分配给
f1
f2
,然后该委托将被调用,然后被丢弃。我之所以提出此问题,只是因为委托调用比普通的早期绑定(甚至虚拟)慢方法调用。这可能不是一个考虑因素,权衡可能是值得的,但仍然值得知道。

要使
正常工作,编译器至少需要一个操作数的显式类型。您可以通过强制转换运算符在此处提供一个显式类型

(a ? (Action<T1,T2,T3,T4>)f1 : f2)(a, long, parameter, list);
(a?(动作)f1:f2)(a,长,参数,列表);

T*
替换为代理参数的实际类型

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

    (test ? (Action<int,int>)M1 : M2)(10, 15)

使用.Net 4进行测试,但应适用于.Net 3.5。正如您所指出的,您可以通过声明委托来实现这一点

我注意到您在很多地方都这样做了。另一个更合适的选择是使用接口。根据a的值实例化两种不同类型中的一种,然后对该对象调用该方法

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

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

将三元操作的结果转换为
操作

((Action<int, int>)(a ? f1 : f2))(int1, int2);
((动作)(a?f1:f2))(int1,int2);

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

var result = cond ? methodA(a,b,c,d) : methodB(a,b,c,d);
但仅此而已


好的,您可以从方法组创建一对委托,但这会增加开销,没有什么好的理由。我不赞成这样做。

我认为下面这样做会更好:


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

这里的强制转换就足够了。不需要分配新的delegate@JaredPar:委托转换(和类型推断)只是语法上的甜点;你仍然会得到一个新的委托实例。在这种情况下,它不会比传统语法更冗长。@Adam,是的。忘记了这没有区别。真的需要“新”吗?JaredPar的答案似乎没有“新”就行了@rskar,它们产生相同的代码。这是@Adam和我一直在讨论的问题。将方法组强制转换为委托并显式创建委托最终产生相同的代码(创建委托)(删除了所有关于运算符命名的注释;充其量只是一个次要主题)抱歉,该语法不适用于VS2008。必须与(a?(操作)f1:f2)(1,null,2.0f)一起使用@rskar我想你可能有一两个圆括号。再试一次,但没有乐趣。我怀疑这是圆括号的东西。实际上,我是从上面复制和粘贴的。我想他是在试图避免复制推送相同参数集的代码,比如C。我怀疑这样做会损失计算速度。“但这会增加开销。。。“在我看来,我们应该对此进行分析。我想最坏的情况下,影响是最小的。@rskar我想我们都知道编写测试将花费比这节省更多的时间,但这仍然是一个不必要的代码缩减…我想我不明白这样做的意义。添加链接到关于此方法的更长讨论,以供将来参考-
((Action<int, int>)(a ? f1 : f2))(int1, int2);
var result = cond ? methodA(a,b,c,d) : methodB(a,b,c,d);