コンテンツへスキップ
ものがたり
戻る

Marekのmcs warning hackingはしばしばcscの一歩先を行っている。今日ネタになっていたのはこんな感じのコードだ:

public class Class1
{
   public virtual void Foo () {}
}

public class Class2 : Class1
{
   [Obsolete]
   public override void Foo () {}
}

.NET 1.1/2.0のcscではwarning対象とされないが、このようなObsoleteAttributeの使い方には問題がある(オーバーライドされた方のメンバーを参照した場合のみwarningが出るのでは一貫性に欠ける)。最近のmcsではちゃんとレポートしてくれるようだ。

追記: 次のバージョンのcscでは同様の警告を出すようになる、とMarekは書いている。たぶんMSのproduct feedbackの返事か何かでそう言われたのだろう。


コメント

ladybug — 01/08/2007 09:21:12

抽象クラスからの汎用的なパラメータによる実装ポイントをobsoleteして、具現クラスで具体的パラメータによる overload を提供する場合、具現クラスのメソッドにだけ obsolete を出したい場合って、ありませんかな?

atsushieno — 01/08/2007 09:50:54

具象クラスが何になるかは、抽象クラスを用いた呼び出しにおいては決定できないので、やはりparams付きメソッドであってもobsoleteは一貫性を欠くことになると思いますが、そういう話ではないですかね?

ladybug — 01/08/2007 10:34:21

class ObsoleteAttribute : WarningAttribute みたいなかんじで WarningAttribute の派生クラスで遊べたら、色々困らないのかなあ。

ladybug — 01/08/2007 10:48:01

最初のコメントのは、
abstract class Class1
{
 public abstract void Foo(object o);
}

public class Class2 : Class1
{
[Obsolete(”call Foo(int)”)]
 public override void Foo(object o) { Foo((int) o); }
 public void Foo(int v) { … }
}

object o = …;
Class1 formatter = GetFormater(o.GetType());
formatter.Foo(o);

は無警告だが、

Class2 intFormatter = new Class2();
intFormatter(o);

は、警告したい、みたいな。(Obsolete の仕事じゃない)

atsushieno — 01/08/2007 11:05:00

派生クラス
意図がよく分かりませんが、BlahAssembly::BlahNamespace.ObsoleteAttributeを対象にすることはないと思います。

具象クラス
Class1 formatter = new Class2();
formatter.Foo(o);
となっていると警告されないわけで、まさしく一貫性に欠ける例であると思います。

ladybug — 01/08/2007 12:32:48

抽象的なインターフェスに対して抽象的な操作 → 警告なし
具体的なインターフェスに対して具体的な操作 → 警告なし
抽象的なインターフェスに対して具体的な操作 → コンパイルできない
具体的なインターフェスに対して抽象的な操作 → コンパイルできるが警告あり

というかんじで、Class1 formatter = new Class2() で警告されないなら、狙い通りってことですね。

ladybug — 01/08/2007 12:44:37

逆(ObsoleteしたメソッドをoverrideしてObsolete消せる)ができちゃうのはマズいと思うけど、たしか警告されますよね。

これは Obsolete じゃなくて WarningAttribute みたいなのが出来ても一緒だとおもうのですが。

ladybug — 01/08/2007 13:07:14

派生クラスは、親クラスに対して設計と実装を変化させることができますが、実装の変更は親クラスとしての動作にも影響を与えますが、設計の変更は親クラスとしての設計に影響を与えてはならない、というかんじかな?

親クラスで設計されたメソッドに、派生クラスで Obsolete という設計の変更がはいっても、それが親クラスとして扱われるかぎり影響しない、というのが OOP の契約関係じゃないのかなあ。

ladybug — 01/08/2007 13:21:26

OOPの〜 というと変なきがしてきた。Perl や JavaScript みたいな prototype な OOPL だと設計に対する影響もだせるし、CLASS 型の OOPL に特異なことか。

atsushieno — 01/08/2007 15:02:16

設計の変更は親クラスとしての設計に影響を与えてはならない
はい、そんな感じの意図です。

WarningAttributeって、現存しないのですが、単に任意の属性を基底クラスとする、名前がObsoleteAttributeになるような属性ではなくて、一部コミュニティで「こういうのがあったらいいなー」って言われているもののことですか?  ObsoleteAttributeはsealedなので、警告を生成できる属性も同様に、sealedでなければならない、という制約があれば問題にならないと思います(既にObsoleteAttributeで実現されている規則なので、不自然な制約には思えません)。

契約関係
これは、宗教的に争いの余地があるような気がしますが、契約関係というものが↑のようなものであったとしても、IsError=trueであるようなObsoleteメンバーを、書き方次第で呼び出せてしまっても、契約関係でそういうことにはなっていないから問題ない、と言えるほど重要ではないように思えます。


この記事を共有:

前の記事
The Definitive Guide to db4o
次の記事
著作権保護延長に反対する署名@青空文庫