扩展方法和源代码的前向兼容性

发布于 2024-08-25 03:28:19 字数 1364 浏览 11 评论 0原文

我想解决在未来开发中使用扩展方法和类接口放大的问题(现在是假设的,但将来可能是真实的)。

示例:

/* the code written in 17. March 2010 */
public class MySpecialList : IList<MySpecialClass> {
    // ... implementation
}
// ... somewhere elsewhere ...
MySpecialList list = GetMySpecialList(); // returns list of special classes
var reversedList = list.Reverse().ToList(); // .Reverse() is extension method
/* now the "list" is unchanged and "reveresedList" has same items in reversed order */

/* --- in future the interface of MySpecialList will be changed because of reason XYZ*/

/* the code written in some future */
public class MySpecialList : IList<MySpecialClass> {
    // ... implementation
    public MySpecialList Reverse() {
        // reverse order of items in this collection
        return this;
    }
}
// ... somewhere elsewhere ...
MySpecialList list = GetMySpecialList(); // returns list of special classes
var reversedList = list.Reverse().ToList(); // .Reverse() was extension method but now is instance method and do something else !
/* now the "list" is reversed order of items and "reveresedList" has same items lake in "list" */

我的问题是:有什么方法可以防止这种情况(我没有找到)?如果现在有办法防止它,有什么方法可以找到这样可能的问题吗?如果现在如何找到可能的问题,我是否应该禁止使用扩展方法?

谢谢。

编辑:

你的回答很有用。 我可以找到代码中使用扩展方法的位置吗?和/或我可以找到代码中使用实例方法但存在具有相同签名的扩展方法的位置吗?

I would like solve the problem (now hypothetical but propably real in future) of using extension methods and maginification of class interface in future development.

Example:

/* the code written in 17. March 2010 */
public class MySpecialList : IList<MySpecialClass> {
    // ... implementation
}
// ... somewhere elsewhere ...
MySpecialList list = GetMySpecialList(); // returns list of special classes
var reversedList = list.Reverse().ToList(); // .Reverse() is extension method
/* now the "list" is unchanged and "reveresedList" has same items in reversed order */

/* --- in future the interface of MySpecialList will be changed because of reason XYZ*/

/* the code written in some future */
public class MySpecialList : IList<MySpecialClass> {
    // ... implementation
    public MySpecialList Reverse() {
        // reverse order of items in this collection
        return this;
    }
}
// ... somewhere elsewhere ...
MySpecialList list = GetMySpecialList(); // returns list of special classes
var reversedList = list.Reverse().ToList(); // .Reverse() was extension method but now is instance method and do something else !
/* now the "list" is reversed order of items and "reveresedList" has same items lake in "list" */

My question is: Is there some way how to prevent this case (I didn't find them)? If is now way how to prevent it, is there some way how to find possible issues like this? If is now way how to find possible issues, should I forbid usage of extension methods?

Thanks.

EDIT:

Yours answer was usefull.
Can I found where in code are used extension methods? And/or can I found where in code are used instance methods but exists extension method with same signature?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

ˉ厌 2024-09-01 03:28:19

看起来您所描述的是以下情况

  1. 在您的产品 MySpecialList 的 V1 中没有 Reverse 方法,因此对 Reverse 的所有调用都绑定到同名的扩展方法
  2. 在产品的 V2 中,MySpecialList 获得了一个 Reverse 方法,现在所有以前对扩展方法的绑定都绑定到实例方法。

如果您想在实例/扩展方法形式中调用 Reverse,则无法阻止这种情况,因为这是设计的行为。如果实例方法至少与扩展方法版本一样好,则实例方法将始终优先于扩展方法。

100% 防止这种情况的唯一方法是将扩展方法作为静态方法调用。例如,

ExtensionMethods.Reverse(list);

与新版本产品绑定到新方法的问题不仅仅限于扩展方法(尽管问题可能更糟)。您可以对类型执行许多操作来改变方法绑定受影响的方式,例如实现新接口、继承或添加新转换

It looks like what you are describing is the following situation

  1. In V1 of your product MySpecialList has no Reverse method so all calls to Reverse bind to an extension method of the same name
  2. In V2 of your product MySpecialList gains a Reverse method and now all previous bindings to the extension method bind to the instance method instead.

If you want to call Reverse in the instance / extension method form there is no way to prevent this as it's the designed behavior. Instance methods will always be preferred over extension methods if they are at least as good as the extension method version.

The only way to 100% prevent this is to call extension methods as static methods. For example

ExtensionMethods.Reverse(list);

This problem of binding to new methods with new version of the product is not just limited to extension methods (although the problem is likely a bit worse). There are many things you can do to a type to alter the way method binding would be affected such as implementing a new interface, inheriting or adding a new conversion

晚雾 2024-09-01 03:28:19

这就是我们编写单元测试的原因。

首先,编写扩展方法。准确地说出它们的名字。因此,有一天,如果扩展方法作为同名类上的真实方法实现,那么很有可能它会与您的扩展方法执行相同的操作,并且不会造成任何破坏。

其次,通过单元测试,您将很快看到什么出了问题,并追踪到它出了问题,因为扩展方法不再被调用,因为该类现在有一个具有该名称的自己的方法。鉴于此,您可以选择重命名方法,将扩展方法作为静态方法调用,或者重写代码以正确使用新方法。

And this is why we write unit tests.

First, write extension methods. Name them precisely. So that one day, IF an extension method is implemented as a real method on the class with the same name, there is a good chance, it does the same thing as your extension method, and nothing breaks.

Secondly, with unit tests, you'll quickly see what broke, and track down that it broke because an extension method is no longer being called, since the class now has a it's own method with that name. Given that, you can choose to rename your method, call your extension method as a static method, OR rewrite your code to properly use the new method.

傲影 2024-09-01 03:28:19

保证这一点的唯一方法是为您的扩展方法指定唯一的名称。这可能很简单,只需在方法前加上您姓名缩写的前缀即可。我知道它看起来很难看,但 99.9% 的时间应该都能用。

The only way to guarantee this would be to give your extension methods unique names. This could be as simple as prefixing the method with your initials. It looks ugly I know, but should work 99.9% of the time.

眼泪也成诗 2024-09-01 03:28:19

在这个特定的实例中,我认为返回新的反向列表(而不是在适当的位置反转列表)的扩展方法首先不应该被称为“Reverse”,而应该是 getReversedList() 或类似的方法。

但是你的观点(关于无副作用的扩展方法无意中被引起副作用的本地方法取代)是有效的;命名约定可能是一个好方法,但是,是的,这是不要不加区别地使用扩展方法的原因(但不足以禁止它们)。

In this particular instance I'd argue that the extension method that returns a new, reversed list (rather than reversing the list in place) shouldn't be called "Reverse" in the first place, but should be getReversedList() or some such.

But your point (about side-effect free extension methods getting inadvertently replaced with side-effect inducing local methods) is valid; a naming convention is probably a good approach, but yes, this is a reason not to use extension methods indiscriminately (but not sufficient to ban them).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文