我正在重构一些代码.
现在有很多地方有这样的功能:
string error;
if (a) {
error = f1(a, long, parameter, list);
}
else {
error = f2(the_same, long, parameter, list);
}
Run Code Online (Sandbox Code Playgroud)
在重构f1和f2之前(虽然很大,但做类似的事情),我想重构为:
string error = (a ? f1 : f2)(a, long, parameter, list);
Run Code Online (Sandbox Code Playgroud)
就像在C中一样.(函数签名是相同的)
但是我收到一个错误:
"错误13无法确定条件表达式的类型,因为'方法组'和'方法组'之间没有隐式转换"
这将允许我通过初始重构给出不变行为来识别参数列表是相同的,并且还在单个位置重构调用,确保在这些各种重构期间所有内容都没有因为我将调用接口更改为方法而被破坏.
我错过了一些小的东西,它允许接近这个的语法工作(而不是一大堆额外的委托类型定义等)?
抱歉编辑,但实际上有一个返回值,是的,不幸的是,它是一个字符串.;-(
现在,我正在解决这个问题:
string error = a ? f1(a, long, parameter, list) : f2(a, long, parameter, list);
Run Code Online (Sandbox Code Playgroud)
问题是参数列表确实很长,并且会被重构,我宁愿先将它们合并,并在我更改时处理编译器错误.
Jar*_*Par 20
为了?工作,编译器需要至少一个操作数的显式类型.您可以通过演员来提供一个
(a ? (Action<T1,T2,T3,T4>)f1 : f2)(a, long, parameter, list);
Run Code Online (Sandbox Code Playgroud)
替换T*为委托参数的实际类型
您必须将其中一个方法实例化为特定的兼容委托类型.没有办法绕过它.不幸的是,这将比你正在寻找的更冗长:
(a ? new Action<T1, T2, T3, T4>(f1) : f2)(a, long, parameter, list);
Run Code Online (Sandbox Code Playgroud)
您将不得不使参数显式,无论是通过使用适合或声明您自己的委托类型的Action(或Func)泛型重载.
这归结为类型分辨率.鉴于表达式:
condition ? tVal : fVal
Run Code Online (Sandbox Code Playgroud)
编译器不会为tVal和找到与公共的赋值兼容的祖先fVal(并且,即使它确实如此,每个可能有效的一系列不同的委托类型可能是巨大的); 如果没有的类型之间分配兼容性tVal和fVal任一方向,编译器让你明确指明,你想要什么.
对于它的价值,你应该知道,采用这种方法将为每个f1或f2每次调用此方法分配一个新的委托,然后该委托将被调用,然后被丢弃.我提出这个问题只是因为委托调用比普通的早期绑定(甚至虚拟)方法调用慢.它可能不是一个考虑因素,权衡可能是值得的,但它仍然值得了解.
如果您指定委托类型,它将允许您执行您要求的操作:
(test ? (Action<int,int>)M1 : M2)(10, 15)
Run Code Online (Sandbox Code Playgroud)
随着声明:
void M1(int a, int b)
{
}
void M2(int a, int b)
{
}
Run Code Online (Sandbox Code Playgroud)
使用.Net 4测试,但应该申请.Net 3.5
正如你所指出的那样,你可以通过声明一个委托来做到这一点.
我注意到你写了你在很多地方这样做.另一种可能更合适的替代方案是使用接口.根据a的值实例化两种不同类型中的一种,然后在该对象上调用该方法.
IFoo foo = a ? new Foo1() : new Foo2();
foo.f(a, long, parameter, list);
Run Code Online (Sandbox Code Playgroud)
如果您有多个方法需要根据当时的值同时更改,a则可以将它们全部包含在同一个界面中,您只需要测试a一次.