ページ 11

C#, baseのbaseにアクセスする方法

Posted: 2016年5月08日(日) 14:13
by せつ
久しぶりにお世話になります。

次のようなクラスが用意されています。(他人が作成したものです)

コード:


public class K : J
{
    public override void update()
    {
        base.update();
    }
}

public class L : K
{
// 大量の記述

    public override void update()
    {
        base.update();

        // 書き換えたい処理
        //
    }

}

ここで、L.fのコメント部分を書き換えたクラスを作りたいと考えています。
しかし、

コード:

public class M : L
{
    public override void update()
    {
        base.update();

        // 書き換えた処理
        //
    }
}
としては、K.update=>書き換えたい処理=>書き換えた処理、となってしまいます。
最終手段としては丸々コピーして class L2 : K を作成する、という事は出来ますが、何かほかに良い方法はないでしょうか。

Re: C#, baseのbaseにアクセスする方法

Posted: 2016年5月08日(日) 23:46
by YuO
仮想メソッドの一部を書き換えるような必要があるならば,書き換える可能性のある部分を仮想メソッドとして分離している必要があります。
今回の場合だと,

コード:

public class L : K
{
    protected virtual void UpdateImpl () { /* ... */ }
    public sealed override void Update () // .NETでは通常publicなメンバーの名前にはPascal Caseを使う
    {
        base.Update();
        UpdateImpl();
    }
}
のようにします。

ただ,今回の内容を見る限り,そもそもMはLなのか,という疑問があります。
Lの実装とMの実装がほぼ同じだからといって,MがLである,とは言えません。
Lの代わりにMのインスタンスを利用しても問題ないのであればよいですが,そうでないならばMはKから派生すべきです。

Re: C#, baseのbaseにアクセスする方法

Posted: 2016年5月09日(月) 17:19
by せつ
前述のとおり他の人が書いたコードで、それをいじることは出来ません。
要はmod作成を行っていたのですが、この部分を変更することを前提としたコードになっていないようです。
また、L型の参照を使用している箇所が見つかったので、Lを複製する、という手段も取れなくなりました。
Lにインターフェースなどを継承していれば、と思ったり。

手段が無いようなら諦めたいと思います。

Re: C#, baseのbaseにアクセスする方法

Posted: 2016年5月10日(火) 21:43
by YuO
一応,方法はありますが……。
  • C++/CLIを使う。
    C++/CLIでは, クラス名::メソッド名 の形で呼び出せるため,直接のベースクラス以外のクラスのメソッドを呼び出すことができます。
  • Reflection.Emitでcallを使うILを書く
    C++/CLIと同様のことを,実行時にコード生成してしまう方法。形式的にはC#のみですが,やることはIL (つまりはCLIにおけるアセンブリ言語) を直接書くような形になります。
サンプルを作ってみました。
複数プロジェクトなので,アーカイブを添付しておきます。
また,githubにも同一の物を上げておきます。
オフトピック
正確に書くなら,githubにpushしたあと,

コード:

git archive --format=zip HEAD > ConsoleApplication1.zip
で作成したのが添付のZIPファイル
どちらにしてもメンテナンス性に欠けるため,可能であれば避けることをお薦めします。