8

この質問は本当に無意味ですが、私はただ興味があります:

これ:

public sealed class MyClass
{
   protected void MyMethod(){}
}

コンパイルされますが、警告が表示されます

これの間:

public sealed class MyClass
{
   public virtual void MyMethod(){}
}

コンパイルしません。純粋な好奇心からですが、これには理由がありますか?

4

9 に答える 9

12

virtualは、メソッド/プロパティの「オーバーライド可能」を宣言するために使用されます。

sealは、クラスを継承できないことを宣言するために使用されます。

そのため、クラスは継承できないため、シール クラスの仮想メソッドをオーバーライドすることはできませんでした。意味がありません。

protectedはメンバーへのアクセスに影響しますが、virtual のように「オーバーライド可能」と宣言していません (ただし、そのように使用されることがよくあります)。したがって、矛盾することはありません。

于 2009-07-21T02:22:40.363 に答える
4

これには正当な理由が見当たりません。保護された MyMethod は MyClass から呼び出すことができますが、派生クラスからは呼び出されません (MyClass はシールされているため)。仮想バージョンは MyClass から直接呼び出すこともできますが、MyClass からクラスを派生させることはできないため、メソッドがオーバーライドを持つことは違法です...

于 2009-07-21T02:25:01.297 に答える
2

エラーは次のとおりです。

CS0549: 'function' は、シール クラス 'class' の新しい仮想メンバーです。

まず第一に、クラスに newprotectedまたはvirtualmembersを含めることは実際には意味がないという事実にもかかわらずsealed、CLI¹ ではそれが可能です。CLI では、IL 命令を使用してシール クラスのメンバーを呼び出すこともできますcallvirtが、コンパイラは IL 命令を自由に置き換えることができcallます。

現在、ECMA-334 (C# 言語仕様) には、コンパイラが上記のエラーを発行する必要があるものは見つかりません。シールされたクラスに新しい仮想メンバーを含める意味がないという理由だけで、Microsoft の実装がエラーを追加したようです。

¹CLI は仮想マシンであり、C# コンパイラはその上で実行されるバイト コードを出力します。そのため、CLI で違法であるほとんどすべての概念は、C# でも違法です。ただし、これは、C# が少し余分に行う場合です (それが問題であるというわけではありません)。

編集: マークアップされた投稿は、OP でそのようなコードを書くことが意味をなさない理由を説明しているようです。しかし、どのルールがコンパイラエラーになったかに関しては、間違っているようです。

于 2009-07-21T02:50:24.280 に答える
2

シールされたクラスは、継承によって保護されたメンバーを持つことができます。メソッドがクラスの一部である場合、そのメソッドがどのようにそこに到達したかは問題ではありません。

最初のケースでは、sealed クラスに保護されたメソッドがあり、sealed クラスが保護されたメソッドを継承した場合と同じです。それでコンパイルします。

好奇心から、与えられた警告は正確には何ですか?

于 2009-07-21T02:32:43.670 に答える
1

シール クラスはサブクラス化できないため、virtual はオプションではありません。したがって、エラー。

これは少しばかげていますが有効なので、警告します。

于 2009-07-21T02:41:54.467 に答える
0

封印されたままWhen applied to a class, the sealed modifier prevents other classes from inheriting from it.

ここで私はあなたに一つずつ説明しようとしています:

public sealed class MyClass
{
   protected void MyMethod(){}
}

クラスを封印されていると宣言した後はそれを継承できず、メソッドとしてはそのオブジェクトを使用してクラスの外部からアクセスできないため、実際には意味がないため、警告が表示されますprotected(また、次のことができることにも注意してください)この子クラスを作成しないので、そのトリックでもこのメソッドを使用することはできません)したがって、実際にはそれを作成する意味がないprotectedため、コンパイラは警告を表示しますが、作成した場合は警告を表示しpublic ませinternalんその場合に役立つため、エラーが発生します。

今2番目のもの:

public sealed class MyClass
{
   public virtual void MyMethod(){}
}

あなたがクラスを封印し、今あなたはあなたのメソッドを仮想として作成しているので、間接的に誰かにそれをオーバーライドするオファーを与えています、そしてそれは継承によってのみ可能であり、ここに問題があります。あなたのクラスは封印されているのであなたはできませんこのclass.soで継承を実行するとvirtual、エラーが発生します。

それがあなたの理解に役立つことを願っています。

参考のために http://msdn.microsoft.com/en-us/library/88c54tsw.aspx

于 2011-12-08T18:29:25.040 に答える
0

仮想メソッドが宣言されている場合、コンパイラはシールされたクラスを使用していくつかの最適化を行うと思います-「vtableを持たない」ことが候補のようです。

ただし、それは単なる推測です。

于 2009-07-21T03:29:22.777 に答える