21

あなたが私に発砲し始める前に、私はこれを行うつもりはありませんが、別の投稿の誰かが可能だと言いました. それはどのように可能ですか?リフレクションを使用して何かから継承することは聞いたことがありません。しかし、私はいくつかの奇妙なものを見てきました...

4

5 に答える 5

17

オーバーライドする仮想関数がなければ、シール クラスをサブクラス化してもあまり意味がありません。

仮想関数を含むシール クラスを記述しようとすると、次のコンパイラ エラーが発生します。

// error CS0549: 'Seal.GetName()' is a new virtual member in sealed class 'Seal'

ただし、仮想関数を基底クラスで宣言することにより (このように)、シールされたクラスに仮想関数を取得できます。

public abstract class Animal
{
    private readonly string m_name;

    public virtual string GetName() { return m_name; }

    public Animal( string name )
    { m_name = name; }
}

public sealed class Seal : Animal
{
    public Seal( string name ) : base(name) {}
}

ただし、問題はまだ残っています。サブクラスを宣言できるようにするために、コンパイラをこっそり通過する方法がわかりません。私は IronRuby を使用してみました (ruby はすべてのハッケティー言語の中で最もハックです)、それでも使用できませんでした。

「封印された」部分はMSILに埋め込まれているので、CLR自体が実際にこれを強制していると思います。コードをロードして逆アセンブルし、「封印された」ビットを削除してから再アセンブルし、新しいバージョンをロードする必要があります。

于 2008-09-30T21:31:53.507 に答える
12

他のスレッドに誤った仮定を投稿して申し訳ありません。正しく思い出すことができませんでした。次の例では、Reflection.Emit を使用して別のクラスから派生する方法を示していますが、実行時に TypeLoadException をスローして失敗します。

sealed class Sealed
{
   public int x;
   public int y;
}

class Program
{
   static void Main(string[] args)
   {
      AppDomain ad = Thread.GetDomain();
      AssemblyName an = new AssemblyName();
      an.Name = "MyAssembly";
      AssemblyBuilder ab = ad.DefineDynamicAssembly(an, AssemblyBuilderAccess.Run);
      ModuleBuilder mb = ab.DefineDynamicModule("MyModule");
      TypeBuilder tb = mb.DefineType("MyType", TypeAttributes.Class, typeof(Sealed));

      // Following throws TypeLoadException: Could not load type 'MyType' from
      // assembly 'MyAssembly' because the parent type is sealed.
      Type t = tb.CreateType();
   }
}
于 2008-10-01T07:43:50.400 に答える
1

可能性があります(できればサイズを大きくします)。freenode の担当者によると、これには、Reflection.Emit を使用してバイト コードを変更し、JIT に新しいバイト コード セットを渡す必要があるとのことでした。

私がその方法を知っているわけではありません...それは彼らが考えたものでした。

于 2008-09-30T21:15:17.870 に答える
1

他の投稿者は、より一般的な読み取り専用の Reflection API ではなく、Reflection.Emit の方針に沿って考えていた可能性があります。

ただし、まだ可能ではありません (少なくともこの記事によると)。しかし、放出されたコードを実際に実行しようとするまでトラップされないものを Reflection.Emit で台無しにすることは確かに可能です。

于 2008-09-30T21:16:44.183 に答える
-3

GenericKeyValueBaseという新しいクラスを作成します

これを入れて

  public class GenericKeyValueBase<TKey,TValue>
    {
        public TKey Key;
        public TValue Value;

        public GenericKeyValueBase(TKey ItemKey, TValue ItemValue)
        {
            Key = ItemKey;
            Value = ItemValue;
        }
    }

さらに、それを継承して、本当にクールな気分であれば、Add / Remove(AddAtおよびRemoveAt)の拡張メソッドを新しい派生クラスに追加(およびコレクション/辞書にする)できます。

ベースに通常のSystem.Collections.Generic.KeyValuePairを使用するが、代わりに上記のコードを使用できる単純な実装例

  class GenericCookieItem<TCookieKey, TCookieValue> : GenericKeyValueBase<TCookieKey,TCookieValue>
    {
        public GenericCookieItem(TCookieKey KeyValue, TCookieValue ItemValue) : base(KeyValue, ItemValue)
        {
        }
    }
于 2009-06-02T01:56:05.900 に答える