这里有趣的问题。我有一个类处理System.Data元素,这些元素是原始编写的,使用具体类作为参数。它最近更新为使用接口,以便我们与其他数据库具有更好的兼容性。
我的问题来自以下方法及其更新版本:
旧:
public bool Transact(Func<DbTransaction, bool> functionBlock)
{
... Stuff ...
}
新:
public bool NewTransact(Func<IDbTransaction, bool> functionBlock)
{
... Stuff ...
}
旧版本导致DbTransaction
对象被吐出,我们可以发送到我们项目中的其他方法,而较新的对象返回IDbTransaction
。我将更新后的版本命名为 NewTransaction ,这样如果最终的新项目(DLL Hell和诸如此类的东西)坐在一起,那么旧的项目就不会被破坏。
我可以将 NewTransact 重命名为 Transact ,它会编译得很好,但是我没有办法调用另一个。我目前的解决方案可以正常工作,但最终 NewTransact 将不再是“新的”。那时,删除旧方法并更改新方法的名称只会导致问题再次出现。
我的问题是:如果它们的名字相同,有没有办法选择调用哪种特定方法?
我猜不会,但我认为这会成为一个很好的问题。
编辑:此问题的关键组成部分是保持向后兼容性。任何需要更新旧软件以继续运行的答案都是无关紧要的。如果我想回去更新其他项目,我会首先简单地做,而不是创建这些重载。
答案 0 :(得分:1)
这是一个有效的示例,以及如何强制调用哪个:
private static readonly Program p = new Program();
private Foo foo;
static void Main(string[] args) {
p.foo = new Foo();
p.foo.IsFoo = true;
p.foo.IsIFoo = true;
// uses Transact(Func<Foo, bool> funcBlock)
var isFoo = p.Transact(f => f.IsFoo == true);
Console.WriteLine("isFoo: {0}", isFoo);
// this is ambiguous
//var isIFoo = p.Transact(f=> (f as IFoo).IsIFoo == true);
// this works
var isIFoo = p.Transact((IFoo f) => f.IsIFoo == true);
Console.WriteLine("isIFoo: {0}", isIFoo);
Console.ReadLine();
}
bool Transact(Func<Foo, bool> funcBlock) {
Console.WriteLine("Transact(Func<Foo, bool> funcBlock)");
return (funcBlock(p.foo));
}
bool Transact(Func<IFoo, bool> funcBlock) {
Console.WriteLine("Transact(Func<IFoo, bool> funcBlock)");
return (funcBlock(p.foo));
}
}
class Foo : IFoo {
public bool IsFoo {
get;
set;
}
public bool IsIFoo {
get;
set;
}
}
interface IFoo {
bool IsIFoo { get; set; }
}
正如其他人所说,编译器将确定调用哪个函数。但在我的例子中,Foo也是一个IFoo,所以我认为这是问题的关键。
输出:
每次评论的Transact(
Func<Foo, bool> funcBlock
)
isFoo:是的的Transact(
Func<IFoo, bool> funcBlock
)
isIFoo:是的
更新
要总结并将其置于问题的范围内,请使用以下方法之一来确定代码应调用的函数:
((DbTransaction transaction) => ...)
......或
((IDbTransaction transaction) => ...)
答案 1 :(得分:0)
将调用编译器根据参数类型选择的方法。
例如:
Func<DbTransaction, bool> f1 = dbt => false;
Func<IDbTransaction, bool> f2 = idbt => false;
// Possible from .NET 4.0 since type parameter T of Func<in T, out TResult> is contravariant.
var f3 = (Func<DbTransaction, bool>)f2;
// Calls Transact with Func<DbTransaction, bool> parameter.
Transact(f1);
// Calls Transact with Func<IDbTransaction, bool> parameter.
Transact(f2);
// Calls Transact with Func<DbTransaction, bool> parameter.
Transact(f3);
答案 2 :(得分:0)
也许将两者都重命名为Transact
,然后在新代码中重命名尝试获取如下所示的方法:
MethodInfo transact = YourType.GetMethod("Transact",new Type[] {typeof(Func<IDbTransaction, bool>)});
然后叫它:
bool returnVal = transact.Invoke(callingObject, new object[]{yourArgumentHere});
这个 应该给你一种方法来调用指定的方法,而旧的代码仍然会使用Transact(Func<DbTransaction, bool> functionBlock)
作为最接近提供的参数的实现。