Почему я могу запечатать класс, реализующий интерфейс, но не могу запечатать члена? - PullRequest
2 голосов
/ 15 декабря 2010

Учитывая этот интерфейс

public interface IMyInterface
{
    string Method1();
}

Почему это действительно

public sealed class InheretedFromInterfaceSealed: IMyInterface
{
    public string Method1()
    {
        return null;
    }
}

Но это не

public class InheretedFromInterfaceWithSomeSealed: IMyInterface
{
    public sealed string Method1()
    {
        return null;
    }
}

И все же это правильный сценарий для абстрактного класса

public abstract class AbstractClass
{
    public abstract string Method1();
}
public class InheretedFromAbstractWithSomeSealed: AbstractClass
{
    public sealed override string Method1()
    {
        return null;
    }
}

Ответы [ 3 ]

6 голосов
/ 15 декабря 2010

Поскольку каждый метод по умолчанию запечатан, за исключением случаев, когда он виртуальный, или если вы не говорите sealed для чего-то, что уже является виртуальным и которое вы переопределяете.

1 голос
/ 15 декабря 2010

Каждый метод в классе по умолчанию закрыт (NotOverridable в VB.NET), если только вы не объявите его как virtual (Overridable в VB.NET).

Как вы сказали, это не в случае с классами. Вы должны указать, что хотите запретить наследование от класса, используя sealed (или NotInheritable в VB.NET).

0 голосов
/ 05 августа 2017

Просто напоминание о том, что методы интерфейса в C # не могут быть sealed.

Рассмотрим следующий код:

interface IFoo
{
    void Bar();
}
class Base : IFoo
{
    public void Bar() { Console.WriteLine("Base.Bar"); }
}
class Derived : Base, IFoo
{
    public new void Bar() { Console.WriteLine("Derived.Bar"); }
}

И затем, если у нас есть var d = new Derived(), у нас будет:

  • d.Bar() пишет Derived.Bar
  • ((Base)d).Bar() пишет Base.Bar
  • ((IFoo)d).Bar() пишет Derived.Bar
  • ((IFoo)(Base)d).Bar() пишет Derived.Bar

Метод интерфейса Bar переопределяется производным классом. Метод sealed - это не интерфейсный метод , а метод Base.

То есть неявная реализация

class ImplicitImpl : IFoo
{
    public void Bar() { Blah; }
}

следует рассматривать как следующую семантически эквивалентную явную реализацию:

class ImplicitImplEquiv : IFoo
{
    public void Bar() { Blah; }
    void IFoo.Bar() { this.Bar(); }
}

Если производный класс ImplicitImplEquiv просто скрывает public void Bar с другим public void Bar, вызов ((IFoo)ref).Bar() все равно вызовет ImplicitImplEquiv.Bar. Но если производный класс также наследует IFoo и предоставляет новую реализацию, интерфейс vtable будет отличаться от интерфейса ImplicitImplEquiv.

Для дальнейшего обсуждения этой темы вы можете прочитать мое сообщение в блоге https://geelaw.blog/entries/csharp-interface-sealed/ (статья только на китайском языке в настоящее время, но содержит хорошие фрагменты кода, которые помогут вам понять проблему).

...