如何隐藏扩展方法不让派生类使用?

5

我有一个基础的抽象类用于实现模板方法模式。

public abstract class OptionalParameter
{
    //Template Method Pattern
    public string GenerateQueryString()
    {
        return this.GenerateQueryStringWithParameters();
    }
}

我有一个适用于所有OptionalParameter类型的扩展方法。

public static class OptionalParameterExtensions
{
    public static string GenerateQueryStringWithParameters(this OptionalParameter optionalParameters)
    {

    }
}

我继承了OptionalParameter类并将其命名为CalendarEventParameter。

public class CalendarEventParameters : OptionalParameter
{

}

当我想要创建CalenderEventParameter的实例时,我看到抽象类中既有GenerateQueryString()方法,也有扩展方法GenerateQueryStringWithParameters()

我不想在派生类中看到它。我试过把扩展方法标记为私有,但这样我也无法从我的抽象类中访问它。

是否可能只允许从基本抽象类调用扩展方法?


3
为什么你想要隐藏这个扩展方法?或者说,为什么你一开始要将它声明为一个扩展方法? - CodeCaster
扩展方法是编译器的一种机制。Intellisense使用“类型”来确定何时适用扩展方法。由于继承,任何继承的类型都将显示其基类型的扩展方法。理论上,可以通过某些VS扩展(通过某些属性)定义隐藏扩展方法列表中的扩展方法。另请参见问题,特别是Jon的想法(为扩展方法设置单独的命名空间)。 - Sinatr
2个回答

5

通常情况下,扩展方法无法对派生类进行隐藏。

只有当其他类在比所有调用扩展方法的程序集更高级别的程序集中时才可能实现(您可以将扩展方法标记为 internal )。

您还可以将扩展方法放置在另一个命名空间中,并在要调用该扩展方法的每个类文件中包含该命名空间。这不是真正的隐藏,但它可能会起到作用。


2
首先,如果您想要一个仅适用于类的扩展方法,并且您控制该类。您可以将该方法作为类的成员。 其次,您希望在类上存在一个方法,但在其派生类上也存在?这不是它应该工作的方式。
尝试使该方法为internal,这样您就可以完全控制它在哪里被调用。如果需要将其设置为public,则可以将其归属于接口,并使用隐式实现,这样只有在对象强制转换时才可用。
您还可以考虑从智能感知中隐藏成员,或者使其过时...
但老实说,这不是面向对象设计的正确方式,请重新考虑您的设计。
值得注意的是,如果您具有与实际方法相同名称和签名的扩展方法,则实际方法优先。因此,您可以为基类添加扩展方法,并在派生类中添加实际方法...
如果您这样做,为什么不直接拥有一个方法并使其虚拟。这样,派生类就可以替换实现。
查看您的模式-请参见代码中的注释:
public abstract class OptionalParameter
{
    public string GenerateQueryString()
    {
        // You are calling the extension method here
        return this.GenerateQueryStringWithParameters();
    }
}

这意味着扩展方法就是默认实现。只需将该方法设置为虚拟的即可:
public abstract class OptionalParameter
{
    public virtual string GenerateQueryString()
    {
        // Default implementation, whatever
    }
}

然后,您可以替换实现:

public class CalendarEventParameters : OptionalParameter
{
    public override string GenerateQueryString()
    {
        // Custom implementation
    }
}

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