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:
- an explicit implementation of this interface
- 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".
精彩评论