experimenting with Visitor pattern and generic method I found a kind of discrepancy in C#.NET. AFAIK C# compiler prefers an explicit overload to a generic method, therefore the following code:
public abstract class A
{
public abstract void Accept(Visitor v);
}
public class B : A
{
public override void Accept(Visitor v)
{ v.Visit(this); }
}
public class C : A
{
public override void Accept(Visitor v)
{ v.Visit(this); }
}
public class D : A
{
public override void Accept(Visitor v)
{ v.Visit(this); }
}
public class Visitor
{
public void Visit(B b)
{ Console.WriteLine("visiting B"); }
public void Visit(C c)
{ Console.WriteLine("visiting C"); }
public void Visit<T>(T t)
{ Console.WriteLine("visiting generic type: " + typeof(T).Name); }
}
class Program
{
static void Main()
{
A b = new B();
A c = new C();
A d = new D();
Visitor v = new Visitor();
b.Accept(v);
c.Accept(v);
d.Accept(v);
}
}
The output produced is (as expected):
visiting B
visiting C
visiting generic type: D
However this Visitor pattern implementation does not allow to exchange the Visitor class. Introducing an abstract class VisitorBase and forwarding the call to the overloads produces smth. unexpected for me....
public abstract class A
{
public abstract void Accept(VisitorBase v);
}
public class B : A
{
public override void Accept(VisitorBase v)
{ v.Visit(this); }
}
public class C : A
{
public override void Accept(VisitorBase v)
{ v.Visit(this); }
}
public class D : A
{
public override void Accept(VisitorBase v)
{ v.Visit(this); }
}
public abstract class VisitorBase
{
public abstract void Visit<T>(T t);
}
public class Visitor : VisitorBase
{
protected void VisitImpl(B b)
{ Console.WriteLine("visiting B"); }
protected void VisitImpl(C c)
{ Console.WriteLine("visiting C"); }
protected void VisitImpl<T>(T t)
{ Console.WriteLine("visiting generic type: " + typeof(T).Name); }
public override void Visit<T>(T t)
{
VisitImpl(t); //forward the call to VisitorImpl<T> or its overloads
}
}
class Program
{
static void Main()
{
A b = new B();
A c = new C();
A d = new D();
VisitorBase v = new Visitor();
b.Accept(v);
c.Accept(v);
d.Accept(v);
}
}
Now the output is:
visiting generic type: B
visiting generic type: C
visiting generic type: D
Do generic methods only prefer generic methods? Why are no explicit overloads called?
Overloading is done statically, so when you call VisitImpl(t), the compiler must pick the single best overloaded method that this call represents (if there is one). Since the type parameter T could be anything, the only method which is compatible is the generic method, and therefore all calls from Visit<T>(T t) call into VisitImpl<T>(T t).
EDIT
It looks like you may be coming from a C++ background, so perhaps it's worth noting that C++ templates are very different from C# generics; in particular, there's no such thing as specialization in C#, which may be why the behavior you see is unexpected. The C# compiler does not emit different code for the different types at which a generic method may be called (that is, the C# compiler calls the same generic method when you call Visit(1) and Visit("hello"), it does not generate specializations of the method at types int and string). At runtime, the CLR creates type specific methods, but this happens after compilation and cannot affect overload resolution.
EDIT - even more elaboration
C# does prefer non-generic methods to generic methods when the non-generic method is statically known to be applicable.
The C# compiler will pick a single method to call at any given call-site. Forget about overloading entirely, and give your methods each a different name; which of those renamed methods can be called at the call-site in question? Only the generic one. Therefore, even when the three names collide and overload resolution kicks in, that is the only overload which is applicable at that site, and is the method chosen.
As I understand it, and I could be very wrong, at compile time the generic function visit actually performs a sort of unboxing of the original type. While we can logically see that the types should run through at compile time, the C# compiler can't make it through the Visit function to the VisitImpl function while holding the types, so the original b.visit(v) is considered unboxed at compile. Given this, it must route through the generic for all types that match when the Visit method is called.
EDIT: To clarify what I mean because I just read my own crap:
The compiler holds the link for b.Visit as a generic call. It fits and is labeled generic.
The compiler holds separate links for Visit->VisitImpl as typed and/or generic methods as necessary.
The compiler can not hold a link from b.Visit (as generic) -> VisitImpl as typed. Since the path from b.Visit() -> VisitImpl must go through a generic, it holds it as a generic type and so the generic VisitImpl is preferred.
It seems you're confusing overloading and overriding.
Overloading is when you provide multiple methods with the same name, that differ in parameter types:
class Foo
|
+- void Qux(A arg)
+- void Qux(B arg)
+- void Qux(C arg)
Overriding is when you provide multiple implementations of the same (virtual) method:
class Foo class Bar : Foo class Baz : Foo
| | |
+- virtual void Quux() +- override void Quux() +- override void Quux()
C# performs single dispatch:
The overload of an invoked method is determined at compile-time.
The implementation of an overridden method is determined at run-time.
The visitor pattern exploits the latter by dispatching the method call to the right implementation of the Visit method. In languages with multiple dispatch, the visitor pattern is not needed because the right overload is chosen at run-time.
Generics are a compiler feature, so only information available at compile time is used to determine what method should be called. What you are doing would require at runtime to determine what the actual type of the variable is. The compiler only knows that variable b is of type A, c is of type A, and d is of type A. It's picking the best overload, which is the generic one, as there is no method that takes A.
Related
public interface A
{
void FirstDemo();
void SecondDemo();
}
public interface B
{
void FirstDemo();
void SecondDemo();
}
public class Demo : A, B
{
void A.FirstDemo()
{
Console.WriteLine("This is a function of first method of interface A");
}
void A.SecondDemo()
{
Console.WriteLine("This is a function of second method of interface A");
}
void B.FirstDemo()
{
Console.WriteLine("This is a function of first method of interface B");
}
void B.SecondDemo()
{
Console.WriteLine("This is a function of second method of interface B");
}
}
static void Main(string[] args)
{
A obj = new Demo();
obj.SecondDemo();
B obj1 = new Demo();
obj1.FirstDemo();
}
This program works properly.
But my confusion is If I implement only one interface in the Demo class then I can give an access modifier in every method of that interface. But when I try to implement both interfaces (In this case: A and B) which consists same methods, within the same class (in this case: Demo class) then I'm not allowed to put public access modifier. why it happens?
Note :
If I use single interface and implement it in Demo class, Then I can use access modifier to all methods which is declared in interface. So what's the issue in multiple interfaces with same methods ?
The distinction is not so much about "1 interface vs 2 interfaces", but rather "implicit vs explicit interface implementations". An explanation as for the "why is a visibility modifier forbidden" part of the question, I'll refer to question Why in C# does one need to mention the access modifier for implementation of an interface property?.
(Explicit interface implementations are implicitly public. Yes, you read that correctly.)
C# allows you to implement a single interface both implicitly and explicitly and they become different methods. The static type of the object determines which method to call:
interface IFace {
void Method();
void OnlyImplicit();
void OnlyExplicit();
}
public class Obj : IFace {
public void Method() {
Console.WriteLine("implicit implementation");
}
void IFace.Method() {
Console.WriteLine("explicit implementation");
}
public void OnlyImplicit() {
Console.WriteLine("only implemented implicitly");
}
void IFace.OnlyExplicit() {
Console.WriteLine("only implemented explicitly");
}
public void Main() {
Obj o = new Obj(); // or: var o = new Obj();
IFace i = o;
o.Method(); // call of implicit impl
i.Method(); // call of explicit impl
o.OnlyImplicit(); // call of implicit impl
i.OnlyImplicit(); // call of implicit impl
i.OnlyExplicit(); // call of explicit impl
// compile error, method is implemented explicitly,
// can only be called when static type is interface;
// cannot be called when static type is the class' type
// (this is not so obvious):
o.OnlyExplicit();
}
}
In order to use an object you need an interface :-).
You can implement una interface implicitly and the other explicitly.
You can not provide multiple different implementations of the same interface method. Otherwise how the compiler will choice the implementation to use?
Suppose you implicit implements A and explicit B:
var demo = new Demo();
demo.FirstDemo(); // it uses public implementation (Demo class interface) that is A
var demoB = (B)demo;
demoB.FirstDemo(); // it uses B interface
In the example below, is there a way for a method of the implementing class to explicitly tell the compiler which interface member it implements?
I know it's possible to resolve ambiguity between interfaces, but here it is within one interface.
interface IFoo<A,B>
{
void Bar(A a);
void Bar(B b);
}
class Foo : IFoo<string, string>
{
public void Bar(string a) { }
public void Bar(string b) { } // ambiguous signature
}
I don't think that you can solve that directly by only using one interface because the method signatures may unify for some cases.
If you realy need this feature I think you've to introduce a new interface that will be derived by foo.
public interface IBar<T>
{
void Bar(T t);
}
public interface IFoo<A, B> : IBar<A>
{
void Bar(B b);
}
Now you're able to explicitly implement both interfaces:
public class Foo : IFoo<string, string>
{
void IFoo<string, string>.Bar(string b)
{
Console.WriteLine("IFoo<string, string>.Bar: " + b);
}
void IBar<string>.Bar(string t)
{
Console.WriteLine("IBar<string>.Bar: " + t);
}
}
But if you want to use it you've to cast your instance to the special interface:
var foo = new Foo();
((IFoo<string, string>)foo).Bar("Hello");
((IBar<string>foo).Bar("World");
This prints as expected:
IFoo<string, string>.Bar: Hello
IBar<string>.Bar: World
Hopefully this will help you. I don't think that there is another way of doing that.
It is possible to implement only one interface explicitly so that you only need to cast if you want to call the other method.
You just need to remove the duplicate line:
interface IFoo<A, B>
{
void Bar(A a);
void Bar(B b);
}
class Foo : IFoo<string, string>
{
public void Bar(string a) { }
}
In this case having a single implementation of void Bar(string a) implements both methods of the interface.
Actually calling the interfaces is much harder though. You need reflection.
You can't do that.
Bar() will be ambiguous in this situation. Consider changing the interface methods to BarA(), BarB().
Also, consider making A and B more meaningful names (e.g., IFoo<TKey, TValue>), then your methods could be BarKey() and BarValue().
Why we can't use base keyword to use base class methods in static methods?
Both are available at compile time.
class A
{
public virtual void Func(int a=4){
Console.WriteLine(" A Class: "+a);
}
}
class B : A
{
public new void Func(int a = 12)
{
Console.WriteLine(" B Class: "+ a);
}
}
class C : B
{
public static void Func()
{
base.Func(); // why not ????
}
}
public class Program
{
public static void Main(string[] args)
{
B ob = new C();
ob.Func();
Console.ReadLine();
}
}
Because base keyword is referring to the base class of the current class instance. But you do not have a current instance in static methods - they are static not instance.
You will be able to call B.Func() if you made the Func() method static in class B.
The C# Language Specification states in section 10.6.4 Override methods (emphasis mine):
A compile-time error occurs unless all of the following are true for an override declaration:
...
The overridden base method is a virtual, abstract, or override method. In other words, the overridden base method cannot be static or non-virtual.
Theoretically, it might be possible to look at the base class of the referenced type. After all, the inheritance relationship between classes is defined on the type, not the instance. For example, if I have class A: B, when presented with A.Foo(), the compiler could look for a static virtual method in B called Foo after looking in class A or for base in A.Foo() to return a list of static methods in B. However, I suspect this is a compiler optimization and language simplification to avoid having to handle references to a list of static methods only and the confusion it would cause.
After reading this article & that article - I got confused.
It says :
If there are two methods at different levels of the hierarchy, the
"deeper" one will be chosen first, even if it isn't a "better function
member" for the call.
Also -
It turns out that if you override a base class method in a child
class, that doesn't count as declaring it.
Now let's go back to my question :
Case 1
public class Base
{
public virtual void Foo(int x) { "1".Dump();}
}
public class Child : Base
{
public void Foo(object x) { "3".Dump();}
public override void Foo(int x) { "2".Dump();}
}
void Main()
{
Child c = new Child();
c.Foo(10); //emits 3
}
OK.According to the article
"deeper" one will be chosen first, even if it isn't a "better function. and it doesn't count the override...
So it is right and the program emits "3". ( Foo(object x) is executed)
Let's change line order of 1 line :
Case 2
public class Base
{
public virtual void Foo(int x) { "1".Dump();}
public void Foo(object x) { "3".Dump();} //<line being moved here
}
public class Child : Base
{
public override void Foo(int x) { "2".Dump();}
}
void Main()
{
Child c = new Child();
c.Foo(10); //emits 2 !!!!
}
Now it emits "2".
Now lets change all int to object and all object to int :
Case 3
public class Base
{
public virtual void Foo(object x) { "1".Dump();}
public void Foo(int x) { "3".Dump();}
}
public class Child : Base
{
public override void Foo(object x) { "2".Dump();}
}
void Main()
{
Child c = new Child();
c.Foo(1); //emits "3"
}
Questions :
Question#1 : in case 2 , Child inherited the Foo(object x) from its father AND he also overrides a method.
but didnt we just say that :
It turns out that if you override a base class method in a child
class, that doesn't count as declaring it
???
in fact, we didnt also declared the inherited function ... so what is the rule here in this situation ?
Question#2 : in case 3 , Child inherited the Foo(int x) from its father AND he also overrides a method.
but now , he chooses its father function....
it seems like override is winning only if it has exact match.
again , what is the rule here in this situation ?
See member lookup process of a name N in a type T (in your case member Foo in type Child):
First, the set of all accessible (Section 3.5) members named N declared in T and the base types (Section 7.3.1) of T is constructed:
virtual void Foo(int x) // Base
void Foo(object x) // Base
override void Foo(int x) // Child
Declarations that include an override modifier are excluded from the set.
virtual void Foo(int x) // Base
void Foo(object x) // Base
Argument has an integer type. So, best choice here is (argument type matches parameter type)
virtual void Foo(int x) // Base
And this method called. But it is virtual method. And its invoked due to virtual method invocation mechanism:
For every virtual method declared in or inherited by a class, there
exists a most derived implementation of the method with respect to
that class. The most derived implementation of a virtual method M with
respect to a class R is determined as follows:
If R contains the introducing virtual declaration of M, then this is the most derived implementation of M.
Otherwise, if R contains an override of M, then this is the most derived implementation of M.
Otherwise, the most derived implementation of M with respect to R is the same as the most derived implementation of M with respect to
the direct base class of R.
And what is most derived implementation of virtual void Foo(int x) method with respect to a class Child? Yes, it is
override void Foo(int x) // Child
Which is invoked.
Same rules applied in your third sample. But when two options left after overridden method removing, best choice (due to argument type) is non-virtual method.
There are 2 things happening:
When selecting the method to invoke, the compiler will obey the rules as per the linked articles - ie. a deeper method will be chosen before a shallower one even if the shallower one is a more specific match
If you call an overridden method, it will always call the overridden method (this is separate to selecting which method to call), the "only" way to call the base method is from the subclass and using base.MyMethod(..)
So basically the lookup rules can choose the method taking an int if it's on a deeper class, but when the method gets called, if it's been overridden it will call the method taking an int on the child class.
I think you are just messing up your facts by reading the two articles.. It should behave like any other normal overridden function as there is no overloading in the child class and thus there is nothing to choose from.. Lets take a simple example:
public class A
{
public virtual void Foo()
{
Console.WriteLine("A.Foo() called");
}
}
public class B: A
{
public override void Foo()
{
Console.WriteLine("B.Foo() called");
}
}
void Main()
{
new B().Foo();
}
What is the expected output? Obviously without thinking twice anyones gonna say B.Foo() called. Well in your case the very same thing is happening. It doesnt matter that the base class has a better overloaded method, the child class just wins it.. Dont over-complicate things..
About case 3, I am not totally sure about this one, but what happens here is that the compiler tries the implicit conversion to object and then it finds that there is a deeper method with the same signature and thus the rule
if there are two methods at different levels of the hierarchy, the
"deeper" one will be chosen first, even if it isn't a "better function
member" for the call
and now once it goes to the base class it notices that there is a better method that can be used and hence calls that method..
P.S: The explanation above is based on the results that have been observed and might not necessarily be the exact reasons for the above seen behavior.
When i need to pass a Generic Type I can use the Syntax
(Example : Ofcourse it is not a Generic Method)
public void Sample(T someValue)
{
......
}
What is the benefit of declaring Sample<T> ?
I mean
public void Sample<T> (T someValue)
{
......
}
Generic types and generic methods are very different things. It sounds like you have a generic type:
class SomeType<T> {
public void Sample(T someValue) {...}
}
and are discussing having a generic method inside it:
class SomeType<T> {
public void Sample<T>(T someValue) {...}
}
These are very different. In the first, inside Sample, then T means "the T that got passed to SomeType<T>". In the second, inside Sample, this is a separate and independent T - "the T that got passed to Sample<T>". In fact, calling it T (in this case) is a mistake. You could have, for example:
var obj = new SomeType<int>(); // here T for SomeType<T> is int
obj.Sample<decimal>(123.45M); // here T for Sample<T> is decimal
Note that there is no easy way (within Sample<T>) of saying "the T in SomeType<T>" - hence why you should rename the method's generic type parameter.
There are valid scenarios for this type of scenario (generic methods on generic types), for example (and note the new name):
class SomeType<T> {
public void Sample<TActual>(TActual someValue) where TActual : T, new() {...}
}
This allows us to do some very interesting things in terms of inheritance, etc - or you might want a generic method that has little or no relation to T. That is fine too.
For this to work:
public void Sample(T someValue)
{
......
}
The type T has to be declared in the system already. And the method will only accept the type T or its derivatives.
By declaring this:
public void Sample<T> (T someValue)
{
......
}
you say the method will accept any type that comes.
Consider the following:
class SomeClass<T>
{
public void Sample(T value)
{
// code goes here
}
}
or this:
class SomeClass
{
public void Sample<T>(T value)
{
// code goes here
}
}
In the first case, for all calls to Sample in a specific instance T will be the same type. In the second case each call in a specific instance can have its own type of T, since the generic type argument is supplied with the method call.
The second approach can have many uses, but one that I have used myself sometimes is in factory methods:
public static class SomeFactory
{
public static T CreateSomeObject<T>()
{
T result = Activator.CreateInstance<T>();
// perform any extra initialization
return result;
}
}
You can use the 2nd example if your class isn't generic. It means you can make just that method generic. If your class is generic, you should use your 1st example.