开发者

Reflecting over classes in .NET produces methods only differing by a modifier

I'm a bit boggled by something, I hope the CLR gearheads can help. Apparently my gears aren't big enough.

I have a reflector utility that generates assembly stubs for Cola for .NET, and I find classes have methods that only differ by a modifier, such as virtual. Example below, from Oracle.DataAccess.dll, method GetType():

class OracleTypeException : System.SystemException {
    virtual  string ToString ();
    virtual  System.Exception GetBaseException ();
    virtual  void set_Source (string value);
    virtual  void GetObjectData (System.Runtime.Serialization.SerializationInfo info,开发者_高级运维 System.Runtime.Serialization.StreamingContext context);
    virtual  System.Type GetType (); // DeclaringType Exception
    virtual  bool Equals (object obj);
    virtual  int32 GetHashCode ();
    System.Type GetType (); // DeclaringType Object
}

What is this?

I have not been able to reproduce this with C# and it causes trouble for Cola as it thinks GetType() is a redefinition, since the signature is identical.

My method reflector starts like this:

static void DisplayMethod(MethodInfo m)
{
    if (
       // Filter out things Cola cannot yet import, like generics, pointers, etc.
       m.IsGenericMethodDefinition || m.ContainsGenericParameters || m.ReturnType.IsGenericType
       || !m.ReturnType.IsPublic
       || m.ReturnType.IsPointer || m.ReturnType.IsByRef
       || m.ReturnType.IsMarshalByRef
       || m.ReturnType.IsImport
       )
   return;

   // generate stub signature
   // [snipped]
}

SOLVED: non-virtual GetType() comes from System.Object. The deriving class shadowed System.Object.GetType() with a virtual method.


This is possible. Here's a code snippet that compiles just fine:

public class OracleTypeException : SystemException, _Exception
{
    public virtual Type GetType()
    {
        throw new NotImplementedException();
    }

    Type _Exception.GetType()
    {
        throw new NotImplementedException();
    }
}

It relies on the fact that SystemException implements _Exception which itself defines the GetType method. So here we have:

  1. an explicit implementation of this interface
  2. a GetType method that hides the one coming from System.Object.

By the way the compiler would generate a warning about it.


I would check:

  • is it static?
  • is it an implicit interface implementation?

Note that you can also re-declare methods, which could be a factor; but that would be crazy; however, this shows this:

class Bar {
    new Type GetType() { return null; }
}
static class Program {
    static void Main() {
        var methods = typeof(Bar).GetMethods(
              BindingFlags.Instance | BindingFlags.Static
            | BindingFlags.Public | BindingFlags.NonPublic);
        foreach (var method in methods) {
            Console.WriteLine(method.Name);
        }
    }
}


This class should exhibit the same behavior:

  class Something {
    public virtual Type GetType() {
      throw new NotImplementedException();
    }
  }

Since every class inherits from System.Object, it also inherits the non-virtual Object.GetType() method. Redeclaring the method as virtual (note that not even the "new" keyword is needed) hides the original inherited GetType method.

Not sure what this tool requires, but I suppose you'll need to rename the hidden inherited method with something like "Object_GetType".

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜