基本クラスで抽象としてマークされているライブラリ クラスでプロパティ set-accessor を呼び出します。実行時に、クラスが基本クラスの基になるインターフェイスのみを実装し、そこから派生していないライブラリの別のバージョンに対してアプリケーションを強制的に実行します。
興味深いことに、.NET はコードを実行しますが、プロパティを設定しても効果はありません。舞台裏で何が起こっているのですか?
問題のあるコード:
MyDbParameter param = new MyDbParameter();
param.ParameterName = "p";
Console.Out.WriteLine("ParameterName: " + param.ParameterName);
ライブラリ 2.0 (コンパイル済み)
public sealed class MyDbParameter : System.Data.Common.DbParameter
{
public override string ParameterName
{
get { return _name; }
set { _name = value; }
}
//...
}
ライブラリ 1.0 (実行)
public sealed class MyDbParameter : MarshalByRefObject, IDbDataParameter, IDataParameter
{
public string ParameterName
{
get { return _name; }
set { _name = value; }
}
//...
}
呼び出しコードの MSIL を見ると、仮想呼び出しは基本クラスの MetodTable を介して解決されていると思います。
IL_0001: newobj instance void [Library]Library.MyDbParameter::.ctor()
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: ldstr "p"
IL_000d: callvirt instance void [System.Data]System.Data.Common.DbParameter::set_ParameterName(string)
しかし、コードの実行時には基底クラスは存在しません。どちらも存在しませんDbParameter.set_ParameterName()
。.NETがそれについて文句を言わないのはどうしてですか? 実際に呼び出されるメソッドはどれですか?
アップデート:
サミュエルが示唆したように、クラスを逆コンパイルしSystem.Data.Common.DbParameter
、両方のライブラリに採用しました。私がどこから派生したか、MarshalByRefObject
またはすべてをコメントアウトしたかに関係なく、動作は再現されます-これにより、メイソンの答えを改ざんしたと思います。
しかし、プロセス中に何が起こるかを発見しました: 実際には、ライブラリ 1の他のプロパティのセッター/ゲッターです。前のケースでは、他のプロパティのセッターを実装して、指定された値を無視したため、効果が見られませんでした。それらすべてに自動ゲッター/セッターがある場合、私のコードの出力は実際には正しいです。MyDbParameter
Size
int
疑問が残ります: .NET は、実行時に欠落しているメソッドについて文句を言わないのはなぜですか?