Let's assume that I have two class.
public class A {...}
public class B : A {...}
What I want is to achieve is to override an extension function for both type.
public static void HelperExtension(this A a) {...}
public static void HelperExtension(this B b) {...}
I know that they are not virtual functions or behave like them. However I really wonder compiler behavior in this case.
Is there a way to call the function for type B without resolving its type? Or any auto-resolve suggestions?
This is not overriding - it is overloading, if anything.
It is fine - since the signatures are different, the compiler will not have any problem compiling it, even in the same namespace.
However, which extension method will be called depends on the exact type of the variable.
Now:
Is there a way to call the function for type B without resolving its type? Or any auto-resolve suggestions?
Without casting this is not possible. The extension is bound to the exact type that is being extended, so you need to have the exact type in order to call an extension on it.
This is why most of LINQ is defined on IEnumerable<T>.
As you said, there is no way of just making the extension virtual.
You could implement the entire virtual method pattern yourself through static methods but I have a strong feeling that's not going to be of any practical use to you, it's more of an interesting theoretical solution as the work involved would be prohibitive for something this simple.
If there are a fixed, finite number of possible sub classes you could have the first method have something like:
public static void HelperExtension(this A a)
{
B b = a as B;
if(b != null)
HelperExtension(b);
else
//the rest of the method.
}
You could use a Switch or even a Dictionary<Type, Action<A>> if you have a lot of subclasses, but it would be tedious, hard to maintain, and not support arbitrary inheritors not known at compile time.
Another option is to essentially leverage the compiler's functionality at compile time through the use of dynamic. I strongly advice avoiding it whenever possible, but in this particular case it would allow you to have a single public extension on A, a bunch of private static methods (with a different name) for each sub type, and then a single dispatch call:
public static void HelperExtension(this A a)
{
ExtenstionImplementation((dynamic)a);
}
private static void ExtenstionImplementation(A a){...}
private static void ExtenstionImplementation(B a){...}
private static void ExtenstionImplementation(C a){...}
I recently faced a similar problem. I have a third-party class library containing a hierarchy of class (let's say IBase, Base and Derived, where IBase is actually an interface).
public interface IBase {...}
public class Base : IBase {...}
public class Derived : Base {...}
Then, I have a class of mine which holds a reference ext to IBase. The concrete type of ext may be Base as well as Derived.
public class MyClass {
// other stuff
public IBase ext;
}
What I actually needed was a virtual method AddedMethod() defined within IBase and overridden in each descendant class, but that wasn't viable. So, one could be tempted to define a class containing a set of overloaded extension methods:
public static class MyExtensions
{
public static void AddedMethod(this IBase arg) {...}
public static void AddedMethod(this Base arg) {...}
public static void AddedMethod(this Derived arg) {...}
}
then, call ext.AddedMethod() on MyClass objects. This doesn't work: as extension methods are statically bound, the first method (i.e. AddedMethod(this IBase arg)) gets always called, regardless the actual type of ext.
The problem can be bypassed by defining a single extension method on IBase, then by using reflection to select the correct instance of a private static method whose argument type matches the actual type passed to the extension method:
public static class MyExtensions
{
// just one extension method
public static void AddedMethod(this IBase arg){
// get actual argument type
Type itsType = arg.GetType();
// select the proper inner method
MethodInfo mi = typeof(MyExtensions).GetMethod("innerAddedMethod",
BindingFlags.NonPublic | BindingFlags.Static,
null,
new Type[] { itsType },
null);
// invoke the selected method
if (mi != null) {
mi.Invoke(null, new object[] { arg });
}
}
private static void innerAddedMethod(Base arg) {
// code for Base type arg
}
private static void innerAddedMethod(Derived arg) {
// code for Derived type arg
}
Whether a new derived class Derived2 should be added to the IBase hierarchy, we'll have to simply add to MyExtensions class an overloaded innerAddedMethod() which takes Derived2 as its argument.
Related
I was wondering if it's possible (even via reflection et similia) to get the caller derived-class inside of a called base-class static method.
For example, I've a base-class with a static method defined:
public MyBaseClass {
public static void MyBaseClassStaticMethod() { /** ... **/ }
}
and a derived-from-it class:
public MyDerivedClass : MyBaseClass { }
then I call:
MyDerivedClass.MyBaseClassStaticMethod()
Is it possibile, inside of method MyBaseClassStaticMethod, to know which is the caller derived type?
(i.e. MyDerivedClass)
I just need a string...
Generics in following way can be used to solve your scenario
public class BaseClass<TDerived> where TDerived : BaseClass<TDerived>
{
public static void LogCallerType()
{
Console.WriteLine(typeof(TDerived).Name);
}
}
public class FooClass : BaseClass<FooClass> { }
public class BooClass : BaseClass<BooClass> { }
class Program
{
static void Main(string[] args)
{
FooClass.LogCallerType();
BooClass.LogCallerType();
}
}
This will in turn output the following
1. FooClass
2. BooClass
No, this is not possible - by no means. static methods are not polymorphal and as such this information simply doesn't exist.
Consider redesigning your code.
Update:
Upon compilation, the compiler replaces MyDerivedClass with the class the static method is actually declared on, in your case MyBaseClass.
So even in the IL you don't see MyDerivedClass. The information exists only in your source code. It doesn't exist in your compiled assembly.
A static method is statically bound to a certain class and does not really participate in the inheritance-chain. Thus it does not exist in the derived class. The static method therefor does not know that it was actually used in the derived class.
You can however - through a compiler-trick - access the static member from your derived class. As of this post on MSDN-forum a static member-access from a derived class is translated to a call from the base-class containing the static member. So MyDerivedClass.MyBaseClassStaticMethod is translated to MyBaseClass.MyBaseClassStaticMethod. Thus MethodBase.GetCurrentMethod().DeclaringType will allways return MyBaseClass.
So in short: no, it´s not possible to get the derived type from a static member.
First of all, the static method will not have access to the instance that is calling it. A static method is different from a normal class method in that it does not have access the 'this' reference to a class instance.
If you passed 'this' as a parameter to the static method, then you can try casting it as follows. Assume you have a number of derived class which you want to test for.
public static void MyBaseClassStaticMethod(MyBaseClass callingInstance)
{
MyDerivedClass myDerivedClass = callingInstance as MyDerivedClass;
MyDerivedClass2 myDerivedClass2 = callingInstance as MyDerivedClass2;
MyDerivedClass3 myDerivedClass3 = callingInstance as MyDefivedClass3;
...
// test for which derived class is calling
if (myDerivedClass != null)
...
else if (myDerivedClass2 != null)
...
...
}
Is any difference between :
public void Method1<T>(class1 c, T obj) where T:Imyinterface
And
public void Method2(class1 c, Imyinterface obj)
?
What are the benefits of use the first one method?
As noted, with void methods, there is not much difference in usage.
If you look behind the scenes you will see that with the generic method, .NET will compile a separate method for each type you call it with. This has the effect of avoiding boxing when called with a struct.
The big difference occurs when you use a return type.
public T Method1<T>(class1 c, T obj) where T: IMyInterface
and
public IMyinterface Method2(class1 c, IMyInterface obj)
With the generic version, you get the original type back, so you can continue calling properties or methods (instance or extension) on the original type.
With the non-generic version, you only get back a value of type IMyInterface, so you can only call properties or methods that are part of IMyInterface.
This is most interesting, in my book, when used with extension methods and a fluent-style API.
public static T Move<T>(this T animal) where T : ICanMove
{
return animal;
}
public static T Fly<T>(this T animal) where T : ICanFly
{
return animal;
}
public static T Pounce<T>(this T animal) where T : ICanPounce
{
return animal;
}
Given that Tiger implements ICanMove and ICanPounce and the Eagle implements ICanMove and ICanFly, I can call the above extension methods that apply to the original type. Intellisense will show .Fly() and .Move() available for an Eagle, and .Pounce() and a .Move() for a Tiger.
var birdie = new Eagle();
birdie
.Move()
.Fly()
.Move()
.Fly();
var kitty = new Tiger();
kitty
.Move()
.Pounce()
.Move()
.Pounce();
Here is what it would look like if you implemented Move non-generically:
public static ICanMove Move<T>(this ICanMove animal)
{
return animal;
}
Since an ICanMove interface is returned, the compiler has no idea that it was originally an Eagle or a Tiger, and so you can only use extensions, methods, or properties that are part of the ICanMove interface.
Using a generic method gives you various possibilities with slight signature changes:
public void Method1<T>(class1 c, T obj) where T:Imyinterface, new():
This allows to instantiate new instances of type T.
public T Method1<T>(class1 c, T obj) where T:Imyinterface:
This allows you to use the method without casting it's return value when needed.
public void Method1<T>(class1 c, ref T obj) where T:Imyinterface:
This allows you to assing a new value to obj's reference. Same applies to out.
These are impossible with the non generic version.
While in your scenario it's practically the same (except for the fact that with method accepting interface parameter it will upcast concrete object to interface type) consider slightly different scenario. Let's say we want our method to accept only class that implements two interfaces IMyInterface1 and IMyInterface2 and that otherwise code should not compile :
interface IMyInterface1 { }
interface IMyInterface2 { }
class MyClass : IMyInterface1 { }
public void Method1<T>(Class1 c, T obj) where T : IMyInterface1, IMyInterface2
{
}
If we create method that accepts interface as it's second parameter it will not satisfy the condition because it doesn't restrict user from sending class instance that implements only one interface but doesn't implements the second interface like it is for MyClass and IMyInterface2 in this example.
And what interface should user send ? He don't really know the type that needs to send on compile-time.
This is a good spot to use generic and generic constrains and on the other hand we cannot use single interface parameter.
There is no big difference for void methods.
public void Method1<T>(class1 c, T obj) where T : Imyinterface
equals to
public void Method2(class1 c, Imyinterface obj, Type t)
where t must be Imyinterface.
So if you need to pass some Type to your method, and you need to apply some constraints to that Type at compile-time, use the generic method.
I was wondering if it's possible (even via reflection et similia) to get the caller derived-class inside of a called base-class static method.
For example, I've a base-class with a static method defined:
public MyBaseClass {
public static void MyBaseClassStaticMethod() { /** ... **/ }
}
and a derived-from-it class:
public MyDerivedClass : MyBaseClass { }
then I call:
MyDerivedClass.MyBaseClassStaticMethod()
Is it possibile, inside of method MyBaseClassStaticMethod, to know which is the caller derived type?
(i.e. MyDerivedClass)
I just need a string...
Generics in following way can be used to solve your scenario
public class BaseClass<TDerived> where TDerived : BaseClass<TDerived>
{
public static void LogCallerType()
{
Console.WriteLine(typeof(TDerived).Name);
}
}
public class FooClass : BaseClass<FooClass> { }
public class BooClass : BaseClass<BooClass> { }
class Program
{
static void Main(string[] args)
{
FooClass.LogCallerType();
BooClass.LogCallerType();
}
}
This will in turn output the following
1. FooClass
2. BooClass
No, this is not possible - by no means. static methods are not polymorphal and as such this information simply doesn't exist.
Consider redesigning your code.
Update:
Upon compilation, the compiler replaces MyDerivedClass with the class the static method is actually declared on, in your case MyBaseClass.
So even in the IL you don't see MyDerivedClass. The information exists only in your source code. It doesn't exist in your compiled assembly.
A static method is statically bound to a certain class and does not really participate in the inheritance-chain. Thus it does not exist in the derived class. The static method therefor does not know that it was actually used in the derived class.
You can however - through a compiler-trick - access the static member from your derived class. As of this post on MSDN-forum a static member-access from a derived class is translated to a call from the base-class containing the static member. So MyDerivedClass.MyBaseClassStaticMethod is translated to MyBaseClass.MyBaseClassStaticMethod. Thus MethodBase.GetCurrentMethod().DeclaringType will allways return MyBaseClass.
So in short: no, it´s not possible to get the derived type from a static member.
First of all, the static method will not have access to the instance that is calling it. A static method is different from a normal class method in that it does not have access the 'this' reference to a class instance.
If you passed 'this' as a parameter to the static method, then you can try casting it as follows. Assume you have a number of derived class which you want to test for.
public static void MyBaseClassStaticMethod(MyBaseClass callingInstance)
{
MyDerivedClass myDerivedClass = callingInstance as MyDerivedClass;
MyDerivedClass2 myDerivedClass2 = callingInstance as MyDerivedClass2;
MyDerivedClass3 myDerivedClass3 = callingInstance as MyDefivedClass3;
...
// test for which derived class is calling
if (myDerivedClass != null)
...
else if (myDerivedClass2 != null)
...
...
}
Here's what I am trying to write:
public void Foo<T>(T parameter) {
otherObject.Bar<T>(parameter);
}
The signature of the Bar() method is:
public void Bar<T>(T parameter) where T: class
So I get a compile error because the T in Foo's signature doesn't have the same constraint. Unfortunately I can't write:
public void Foo<T>(T parameter) where T: class {
otherObject.Bar<T>(parameter);
}
because Foo is implementing a method defined in an external interface. Question is:
Can I somehow transpose the T within the method Foo before calling Bar. (Note, I can be sure that T always will be a class - I just need to get past the compiler).
The only way I have found is using reflection but I wonder if there is a simpler trick I'm missing.
You can use the dynamic keyword like this:
public void Foo<T>(T parameter)
{
dynamic p = parameter
otherObject.Bar(p);
}
What's happening is that the resolution of the call to otherObject.Bar is being made at run-time, because one of the parameters has a type of dynamic. Assuming that T is a reference type, the resolution will succeed.
Granted, this ultimately uses reflection (as you've indicated), but the syntax is probably better than what you're using.
Of course, this will give you a run-time error in the event that T is not a class.
public void Foo<T>(T parameter)
{
otherObject.Bar<object>(parameter);
}
Here's a slightly different take on casperOne's answer, using implicit interface implementation:
public void Foo<T>(T parameter) where T: class {
otherObject.Bar<T>(parameter);
}
void IFoo.Foo<T>(T parameter){
Foo((dynamic)parameter);
}
This allows you to include the constraint on anything that knows what specific object type they're calling .Foo on at compile time, while still allowing you to implement the IFoo interface.
If you are the owner of otherObject.Bar, could you not just remove the class constraint? of that method. Or create a new similar method without the constraint?
casperOne. I am not sure your answer is correct, as you have the class constraint on your Foo method. The question stated that this was not possible as Foo was an implementation of an external interface. For instance, the code below does not work.
public void Foo<T>(T param)
{
dynamic xx = param;
this.Bar(param);
}
private void Bar<T>(T param) where T: class {
}
And shows up as an error.
I have found myself in a situation where I have a method on a base class which makes a call to a generic method passing itself as a parameter (via this). In the generic method the type is always the base type, even when I call the method from a derived class.
I need the generic method to know that it is of the derived type and not the base type.
I am not able to change the generic method since it is from a third party app (http://razorengine.codeplex.com/ - Razor.Parse method).
I have found that if I define the method as a generic extension method restricted to types inheriting from my base class that calling this then works but it seems messy to use extension methods for this purpose (though if this is correct usage I'd be happy to hear that). What I am wondering if there is some trick I can use that will convert "this" to the type of the derived object before it gets called (maybe using generics still).
I have included a simplified program below that should be self contained (I'm running it in LINQPad for personal ease). Essentially I want a method defined on A that when called on an instance of B will call Test.WhatType and output "B".
I hope this makes sense.
void Main()
{
var bar = new B();
bar.myGetType();
bar.ExtGetType();
}
class A
{
public virtual void myGetType()
{
Test.WhatType(this);
this.ExtGetType();
}
}
class B : A {}
static class ext
{
public static void ExtGetType<T>(this T obj) where T : A
{
Test.WhatType(obj);
}
}
class Test
{
public static void WhatType<T>(T obj)
{
Console.WriteLine(typeof(T).Name);
}
}
Edit: Changed method name to A.myGetType() since I hadn't even noticed I was overloading accidentally.
N.B. Running this code outputs:
A
A
B
You need to use obj.GetType(). T is bound at compile-time, not a run time and thus typeof(T) returns the compile-time type of T.
If I understand correctly, your problem is that A.GetType() is binding to WhatType<A> as that is all it knows about.
So you have to let class A know about the derived classes.
You can do this with self-referencing generic types. Something like:
class A<T> where T : A<T>
{
public virtual void GetType()
{
Test.WhatType<T>( (T) this );
}
}
class B : A<B> { }
then:
new B().GetType();
will bind to WhatType<B> and so will output B
This method returns the type of the static type (T). It should be implemented as
public static void WhatType<T>(T obj)
{
Console.WriteLine(obj.GetType().Name);
}
Edit:
I just realized what you want is to manipulate A in such a way that the T of the generic method changes. You can either do this via reflection or by adding a switch statement based on the subtype of A and explicitly cast this to B (or whatever class). Of course none of this solutions is good because A would take dependency on its subclasses and reflection plainly sux. Another option is to override the GetType() method in each subclass and thus move the responsibility to the subclasses.