Domanda

Prima di iniziare a spararmi, NON sto cercando di farlo, ma qualcuno in un altro post ha detto che era possibile. Come è possibile? Non ho mai sentito parlare di ereditare da qualcosa usando la riflessione. Ma ho visto alcune cose strane ...

È stato utile?

Soluzione

Senza le funzioni virtuali da sovrascrivere, non ha molto senso sottoclassare una classe sigillata.

Se si tenta di scrivere una classe sigillata con una funzione virtuale, viene visualizzato il seguente errore del compilatore:

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

Tuttavia, puoi ottenere funzioni virtuali in classi sigillate dichiarandole in una classe base (come questa),

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) {}
}

Il problema persiste, tuttavia, non riesco a vedere come è possibile passare oltre il compilatore per consentire di dichiarare una sottoclasse. Ho provato ad usare IronRuby (ruby è il più hackerato di tutti i linguaggi furtivi) ma nemmeno me lo permetterebbe.

La parte 'sigillata' è incorporata nel MSIL, quindi immagino che lo stesso CLR lo imponga effettivamente. Dovresti caricare il codice, smontarlo, rimuovere il bit "sigillato", quindi rimontarlo e caricare la nuova versione.

Altri suggerimenti

Mi dispiace per aver postato ipotesi errate nell'altra discussione, non sono riuscito a ricordare correttamente. Utilizzando l'esempio seguente, usando Reflection.Emit, viene illustrato come derivare da un'altra classe, ma non riesce in fase di esecuzione generando 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();
   }
}

It MIGHT (aumenterei le dimensioni se potessi). Secondo i ragazzi di freenode, ciò implicherebbe la modifica del codice byte, l'utilizzo di Reflection.Emit e la consegna alla JIT di un nuovo set di codice byte.

Non che io SAPERE come ... era proprio quello che pensavano.

L'altro poster potrebbe aver pensato più sulla falsariga di Reflection.Emit invece delle più consuete API Reflection di sola lettura.

Tuttavia, non è ancora possibile (almeno secondo questo articolo ). Ma è certamente possibile rovinare qualcosa con Reflection, ammettendo che non siano intrappolati fino a quando non si tenta di eseguire effettivamente il codice emesso.

Crea una nuova classe chiamata GenericKeyValueBase

mettici dentro

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

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

Ed eredita da questo plus, puoi aggiungere ulteriori metodi di estensione per Aggiungi / Rimuovi (AddAt e RemoveAt) alla tua nuova classe derivata (e trasformala in una raccolta / dizionario) se ti senti davvero cool.

Un semplice esempio di impianto in cui useresti un normale System.Collections.Generic.KeyValuePair come base, ma invece puoi usare il codice sopra

  class GenericCookieItem<TCookieKey, TCookieValue> : GenericKeyValueBase<TCookieKey,TCookieValue>
    {
        public GenericCookieItem(TCookieKey KeyValue, TCookieValue ItemValue) : base(KeyValue, ItemValue)
        {
        }
    }
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top