この質問は本当に無意味ですが、私はただ興味があります:
これ:
public sealed class MyClass
{
protected void MyMethod(){}
}
コンパイルされますが、警告が表示されます
これの間:
public sealed class MyClass
{
public virtual void MyMethod(){}
}
コンパイルしません。純粋な好奇心からですが、これには理由がありますか?
これには正当な理由が見当たりません。保護された MyMethod は MyClass から呼び出すことができますが、派生クラスからは呼び出されません (MyClass はシールされているため)。仮想バージョンは MyClass から直接呼び出すこともできますが、MyClass からクラスを派生させることはできないため、メソッドがオーバーライドを持つことは違法です...
エラーは次のとおりです。
CS0549: 'function' は、シール クラス 'class' の新しい仮想メンバーです。
まず第一に、クラスに newprotected
またはvirtual
membersを含めることは実際には意味がないという事実にもかかわらずsealed
、CLI¹ ではそれが可能です。CLI では、IL 命令を使用してシール クラスのメンバーを呼び出すこともできますcallvirt
が、コンパイラは IL 命令を自由に置き換えることができcall
ます。
現在、ECMA-334 (C# 言語仕様) には、コンパイラが上記のエラーを発行する必要があるものは見つかりません。シールされたクラスに新しい仮想メンバーを含める意味がないという理由だけで、Microsoft の実装がエラーを追加したようです。
¹CLI は仮想マシンであり、C# コンパイラはその上で実行されるバイト コードを出力します。そのため、CLI で違法であるほとんどすべての概念は、C# でも違法です。ただし、これは、C# が少し余分に行う場合です (それが問題であるというわけではありません)。
編集: マークアップされた投稿は、OP でそのようなコードを書くことが意味をなさない理由を説明しているようです。しかし、どのルールがコンパイラエラーになったかに関しては、間違っているようです。
シールされたクラスは、継承によって保護されたメンバーを持つことができます。メソッドがクラスの一部である場合、そのメソッドがどのようにそこに到達したかは問題ではありません。
最初のケースでは、sealed クラスに保護されたメソッドがあり、sealed クラスが保護されたメソッドを継承した場合と同じです。それでコンパイルします。
好奇心から、与えられた警告は正確には何ですか?
シール クラスはサブクラス化できないため、virtual はオプションではありません。したがって、エラー。
これは少しばかげていますが有効なので、警告します。
封印されたまま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
仮想メソッドが宣言されている場合、コンパイラはシールされたクラスを使用していくつかの最適化を行うと思います-「vtableを持たない」ことが候補のようです。
ただし、それは単なる推測です。