更改参数名称而不破坏向后兼容性

时间:2016-06-27 15:46:19

标签: c# backwards-compatibility named-parameters

我正在开发一个c#库,所以我们关注的是打破向后兼容性,但我想知道是否可以更改参数的名称并保持向后兼容性,因为能够使用命名参数?我想要做的一个例子是

[Obsolete("use ChangeSpecificFoo(SpecificFoo specificFoo)")]
public void ChangeSpecificFoo(SpecificFoo foo)
{
    _specificFoo = foo;
}

//Compile error ... already defines a member called 'ChangeSpecificFoo' with the same parameter types
public void ChangeSpecificFoo(SpecificFoo specificFoo)
{
    _specificFoo = specificFoo;
}

只是更改参数名称会产生破坏向后兼容性的潜在风险,因为有人可能会使用ChangeSpecificFoo(foo: someSpecificFoo)之类的命名参数调用该方法,但我们不能通过添加新方法来弃用该方法。正确的参数名称,因为参数名称不包含在方法签名中,因此编译器将其视为重复。

这有什么办法吗?我看到的唯一选择是更改方法名称,因此它不是重复,然后弃用旧方法,或等到我们从参数列表中添加或删除参数并更改参数名称(这可能永远不会发生,因为方法是非常稳定),或者只是进行更改并修复我们在找到它们时使用此库从代码中获得的任何中断。

1 个答案:

答案 0 :(得分:3)

我对此的第一个倾向很简单: DON' T 。参数的名称在方法体外部无关紧要。你是正确的考虑人们通过名字来呼唤它,因此可能会破坏它。但是,仅更改参数名称不会带来任何实际好处。

更改名称的唯一可能原因是重新定义该方法的作用,因为旧名称会导致混淆。在这种情况下,还应该更改方法的名称,以免引入另一种形式的混淆。 (方法签名相同的事实是不更改参数名称的第一个也是更重要的原因。但是,这可能是为了解释你可能想要的。)

但是,如果您仍然坚持保持相同的方法签名,但更改名称,则可以执行此操作。 (同样,我强烈建议你要么根本不改变它,要么重命名方法以继续消除混淆。)

解决这个问题的一种方法是使用两个参数的方法,但使第二个可选。让最后一个参数使用旧名称,然后在方法中分配它。

我还 HIGHLY 建议记录对命名参数的任何使用,以查看您的关注对于将其作为命名参数调用的人是否有效。

public void ChangeSpecificFoo(SpecificFoo specificFoo = null, SpecificFoo foo = null)
{
    if (foo != null && specificFoo == null)
    {
        // Add any other details you can, especially 
        // to figure out who is calling this.
        Log("Someone used a name parameter!!");
    }
    _specificFoo = specificFoo ?? foo;
}

正如Dmitry Bychenko在评论中指出的那样,这不会阻止任何人像这样调用此方法:ChangeSpecificFoo(null, new SpecificFoo()),这将触发日志记录。

他的观察引入了另一个原因,这就是为什么这是一个坏主意:你现在正在为人们引入另一种不正确的方式"打电话给你的方法因此,我会在答案的顶部重复我的建议: DON' T 这样做,除非你真的真的需要更改参数名称