I have the following code in an unit test
public bool TestMethodsOf<T, I>()
{
var impl = typeof(T);
var valid = true;
foreach (var iface in impl.GetInterfaces().Where(i => typeof(I).IsAssignableFrom(i)))
{
var members = iface.GetMethods();
foreach (var member in members)
{
Trace.Write("Checking if method " + iface.Name + "." + member.Name + " is virtual...");
var implMember = impl.GetMethod(member.Name, member.GetParameters().Select(c => c.ParameterType).ToArray());
if (!implMember.IsVirtual)
{
Trace.WriteLine(string.Format("FAILED"));
valid = false;
continue;
}
Trace.WriteLine(string.Format("OK"));
}
}
return valid;
}
which I call by
Assert.IsTrue(TestMethodsOf<MyView, IMyView>());
I want to ensure that all the methods from the interface are declared as virtual. The reason is because I'm applying a spring.net aspect and it will only apply to virtual methods.
The problem I'm having is that implMember.IsVirtual is always true, even when they are not declared as so in the declaring type.
What is wrong with my TestMethodsOf logic?
Cheers
Methods that are implemented from an interface are not virtual by default. You are merely providing an implementation of the contract defined in the interface definition.
An implementing class is free to mark any or all of the methods that implement the interface as virtual. Derived classes can override or provide new implementations. For example, a Document class might implement the IStorable interface and mark the Read( ) and Write( ) methods as virtual .
Yes, interface implementation methods are virtual as far as the runtime is concerned. It is an implementation detail, it makes interfaces work. Virtual methods get slots in the class' v-table, each slot has a pointer to one of the virtual methods.
Interface methods do not have a body - the body is provided by the "implement" class. On implementation of an interface, you must override all of its methods. Interfaces can contain properties and methods, but not fields/variables. Interface members are by default abstract and public.
All methods declared in an interface are marked as virtual abstract
, and all methods that implement interface methods in classes are marked as virtual final
, so the CLR knows it can't just call them directly - it has to do vtable lookups at runtime to call the right implementation. The interface implementations are still virtual, but you can't override them as they're final.
As an example, the following C# definition:
public interface IInterface {
void Method();
}
public class Class : IInterface {
public void Method() {}
}
compiles to the following IL:
.class public interface abstract IInterface {
.method public abstract virtual instance void Method() {}
}
.class public Class extends [mscorlib]System.Object implements IInterface {
.method public specialname rtspecialname instance void .ctor() {}
.method public virtual final instance void Method() {}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With