不破坏向后兼容性的情况下更改参数名称

4

我正在研究一项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),但我们不能通过添加正确参数名称的新方法来弃用该方法,因为参数名称不包括在方法签名中,所以编译器将其视为重复。
有没有什么方法可以解决这个问题?我看到的唯一选择是更改方法名称,使其不重复,然后弃用旧方法;或者等待我们从参数列表中添加或删除参数,并在那时更改参数名称(这可能永远不会发生,因为该方法已经相当稳定);或者只需进行更改并在发现使用此库的代码时修复任何错误。

从功能上讲,这两种方法完全相同。在您的代码中使用其中任何一种都不会有任何区别。 - Andrew
1
@JonSkeet 我明白你的意思,但现在我想知道为什么会这样?那似乎是一个愚蠢的方式去做... - Andrew
4
@Andrew:在多个参数类型相同的情况下,可读性有了巨大的提高...而且可选参数的实用性也大大增强,因为它允许指定任何可选参数。 - Jon Skeet
2
我会添加/更新XML注释块以澄清。 - Ňɏssa Pøngjǣrdenlarp
1
@Andrew 为了改变参数名称而改变参数名称是一个非常小的问题。在实际情况下,这种情况几乎不会发生,特别是当你不拥有将调用你的方法的所有代码时。正如一直以来的情况一样,Jon Skeet提供了许多例子,说明在(潜在的)罕见情况下你会选择使用命名参数。 - krillgar
显示剩余7条评论
1个回答

3
我的第一反应很简单:不要。方法体外部参数的名称不重要。你考虑到别人通过名称来调用它,因此可能会破坏它,这是正确的。然而,只更改参数名称并没有实际益处。
更改名称的唯一可能原因是因为旧名称会导致混淆,需要重新定义该方法的作用。在这种情况下,方法名称也应更改,以避免引入另一种形式的混淆。(方法签名相同是不更改参数名称的第一个和更重要的原因。然而,这可以潜在地解释您为什么想要这样做。)
如果您坚持保持相同的方法签名但更改名称,可以这样做。 (再次强烈建议您根本不要更改它,或者同时重命名该方法以继续消除混淆。)
解决此问题的一种方法是将两个参数都传递给该方法,但使第二个参数成为可选项。使最后一个参数使用旧名称,然后在方法内部进行赋值。
我还强烈建议记录任何使用命名参数的情况,以查看您是否担心人们会按命名参数调用它。
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()),这将触发日志记录。
他的观察引入了另一个原因,说明这是一个坏主意:您现在为人们“不正确”调用您的方法引入了另一种方式。因此,我会重申我在答案开头的建议:不要这样做,除非您真的非常非常需要更改该参数名称。

从技术上讲,我可以调用 ChangeSpecificFoo(null, new Foo()); 而不使用命名参数,这个调用将被记录为命名调用。 - Dmitry Bychenko
是的,但是这样做也会记录某人以你不想要的方式调用它的情况。我将编辑我的答案以包含该警告。无论如何,这都是一个可怕的想法。但是,如果你有那个0.0000001%的极端情况,真的需要这样做,这里有一个想法。 - krillgar
1
为了澄清一下,我们寻求更改参数名称的原因基本上完全是为了内部维护。显然,这个例子是过于简化的,但是继续以同样的例子来说明,我们已经有一个名为Foo的对象,因此在看到一个名为foo的参数四处游荡时感到困惑,而实际上它是一个SpecificFoo。我们可能会考虑将方法顶部的参数重命名,以避免混淆。如果混淆出现在方法的命名中,那么我们只需更改方法名称,但它已经拥有我们想要的名称。 - TJ Rockefeller
是的。如果它与具有相同名称的成员变量造成混淆,那么重命名其他人看不到的变量是正确的做法。 - krillgar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接