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.Emit 的思路思考,而不是更常见的只读反射 API。

但是,仍然不可能(至少根据这篇文章)。但是,在您尝试实际执行发出的代码之前,肯定有可能用 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;
        }
    }

并且继承它加上你可以添加额外的扩展方法添加/删除(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 回答