問題
ソースコードにアクセスできない既存のライブラリを使用しています。このライブラリは AST を表します。
この AST の一部をコピーしたいのですが、その過程で変数への参照の名前を変更します。Expression オブジェクトを保持する AssignCommand オブジェクトが存在する可能性があるため、各オブジェクトを独自の関数でコピーできるようにして、それらを再帰的に呼び出すことができるようにしたいと考えています。ただし、ライブラリのコードにアクセスできないため、 などのメソッドを追加することはできませんCopyAndRename(string prefix)
。
したがって、私のアプローチは、いくつかのオーバーロードを持つ単一の関数を作成することでしたRename
。したがって、次のような家族機能があります。
public static Command Rename(Command cmd, string prefix)
public static AssignCommand Rename(AssignCommand cmd, string prefix)
public static AdditionExpressionRename(AdditionExpression expr, string prefix)
....
関数は で構成されます。List<Command>
ここで、AssignCommand
は のサブクラスですCommand
。Command
-function に aを渡すだけRename
で、ランタイムが最も具体的なものを見つけると仮定しました。ただし、そうではなく、すべてのコマンドが に渡されCommand Rename(Command cmd, string prefix)
ます。これはなぜですか?醜い操作を使用せずに、呼び出しを正しい関数に委任する方法はありis
ますか?
最小限の例
この問題を次の NUnit-Testcode に分解しました
using NUnit.Framework;
public class TopClass{
public int retVal;
}
public class SubClassA : TopClass{ }
[TestFixture]
public class ThrowawayTest {
private TopClass Foo (TopClass x) {
x.retVal = 1;
return x;
}
private SubClassA Foo (SubClassA x) {
x.retVal = 2;
return x;
}
[Test]
public void OverloadTest(){
TopClass t = new TopClass();
TopClass t1 = new SubClassA();
SubClassA s1 = new SubClassA();
t = Foo (t);
t1 = Foo (t1);
s1 = Foo (s1);
Assert.AreEqual(1, t.retVal);
Assert.AreEqual(2, s1.retVal);
Assert.AreEqual(2, t1.retVal);
}
}
つまり、私の質問は次のようにis
要約できます。
拡張方法
また、次のように拡張メソッドを使用してみました。上記のアプローチの構文糖衣にすぎないため、これは問題を解決しませんでした。
using NUnit.Framework;
using ExtensionMethods;
public class TopClass{
public int retVal;
}
public class SubClassA : TopClass{ }
[TestFixture]
public class ThrowawayTest {
private TopClass Foo (TopClass x) {
x.retVal = 1;
return x;
}
private SubClassA Foo (SubClassA x) {
x.retVal = 2;
return x;
}
[Test]
public void OverloadTest(){
TopClass t = new TopClass();
TopClass t1 = new SubClassA();
SubClassA s1 = new SubClassA();
t.Foo(); s1.Foo(); t1.Foo();
Assert.AreEqual(1, t.retVal);
Assert.AreEqual(2, s1.retVal);
Assert.AreEqual(2, t1.retVal);
}
}
namespace ExtensionMethods{
public static class Extensions {
public static void Foo (this TopClass x) {
x.retVal = 1;
}
public static void Foo (this SubClassA x) {
x.retVal = 2;
}
}
}