在你开始向我开火之前,我不想这样做,但是另一篇文章中有人说这是可能的。怎么可能呢?我从未听说过使用反射从任何东西继承。但我看到了一些奇怪的事情......
如果没有要重写的虚函数,对密封类进行子类化就没有多大意义。
如果您尝试编写一个包含虚函数的密封类,您会收到以下编译器错误:
// 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 本身实际上强制执行了这一点。您必须加载代码,反汇编它,删除“密封”位,然后重新组装它,并加载新版本。
使用以下示例,使用 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();
}
}
它可能(如果可以的话会增加尺寸)。 根据 freenode 上的人的说法,这将涉及使用 Reflection.Emit 修改字节代码,并向 JIT 传递一组新的字节代码。
并不是说我知道如何......这只是他们的想法。
另一位发帖者可能更多地考虑的是 Reflection.Emit,而不是更常见的只读 Reflection API。
但是,仍然不可能(至少根据这篇文章)。 但是,Reflection.Emit 确实有可能搞砸一些事情,这些事情在您尝试实际执行发出的代码之前不会被捕获。
创建一个名为 GenericKeyValueBase 的新类
把这个放进去
public class GenericKeyValueBase<TKey,TValue>
{
public TKey Key;
public TValue Value;
public GenericKeyValueBase(TKey ItemKey, TValue ItemValue)
{
Key = ItemKey;
Value = ItemValue;
}
}
如果您感觉真的很酷,则可以继承该附加功能,为新的派生类添加用于添加/删除(AddAt 和 RemoveAt)的附加扩展方法(并使其成为集合/字典)。
一个简单的实现示例,您可以使用普通的 System.Collections.Generic.KeyValuePair 作为基础,但也可以使用上面的代码
class GenericCookieItem<TCookieKey, TCookieValue> : GenericKeyValueBase<TCookieKey,TCookieValue>
{
public GenericCookieItem(TCookieKey KeyValue, TCookieValue ItemValue) : base(KeyValue, ItemValue)
{
}
}