如何通过扩展方法隐藏成员方法

11
public static class MyClass
{
    public static void Add<T>(this List<T> list, T item)
    {
        list.Add(item);
        Console.WriteLine(item.ToString());
    }
}

那么

List<string> list = new List<string>(){"1","2"};
list.Add("3");

但是成员方法将被调用。

有没有任何方法可以这样调用我的扩展方法

我不想这样调用它:

MyClass.Add(list, item)

1
即使 list.Add("3") 覆盖了 List.Add 并调用了您的扩展方法,您仍应该期望 list.Add(item) 做同样的事情,导致无限递归。 - Kobi
我明白了,我的问题只是出于好奇心,我提供了一段示例代码来展示我的意图,不过你说得对。 - Jahan Zinedine
2个回答

10

你不能这样做。实例方法 总是 优先于扩展方法,前提是它们适用。只有在无法找到非扩展方法选项时,成员解析才会考虑扩展方法。

我建议您简单地重命名方法 —— 除非重点是透明地使用现有代码调用此方法。

如果将其更改为接受 IList<T> 而不是 List<T>,则可以创建一个包装类型,该类型实现 IList<T> 并将所有调用委托到包装的列表,同时执行任何额外任务。然后,您还可以编写一个扩展方法到 IList<T>,用于创建包装器-这将允许在某些情况下使用更流畅的语法。个人而言,我更喜欢包装器方法而不是派生新集合类型的方法,因为这意味着您可以将其与现有集合一起使用,从而使代码更改可能更小...但这完全取决于您想要做什么。


7

实例方法总是优先于扩展方法,所以不行。

在这里做正确的事情似乎应该是多态性 - 但请注意,List<T>不提供virtual方法。不过,Collection<T>提供了:

using System;
using System.Collections.ObjectModel;
class MyClass<T> : Collection<T> {
    protected override void InsertItem(int index, T item) {
        base.InsertItem(index, item);
        Console.WriteLine("Added:" + item.ToString());
    }
    protected override void SetItem(int index, T item) {
        base.SetItem(index, item);
        Console.WriteLine("Set (indexer):" + item.ToString());
    }
    // see also ClearItems and RemoveItem
}

2
多态 - 这是一个狡猾的重载吗? ;) - Mitch Wheat
但是重载也被称为“特定多态”,这没有任何问题。 - Jahan Zinedine

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