C# Overloaded method invocation with Inheritance [duplicate] - c#

This question already has answers here:
Different behaviour of method overloading in C#
(3 answers)
Closed 9 years ago.
I wonder what is the reason for the invocation of the method that prints "double in derived". I didn't find any clue for it in the C# specification.
public class A
{
public virtual void Print(int x)
{
Console.WriteLine("int in base");
}
}
public class B : A
{
public override void Print(int x)
{
Console.WriteLine("int in derived");
}
public void Print(double x)
{
Console.WriteLine("double in derived");
}
}
B bb = new B();
bb.Print(2);

Straight from the C# spec (7.5.3 Overload resolution):
the set of candidates for a method invocation does not include methods marked override (§7.4), and methods in a base class are not candidates if any method in a derived class is applicable (§7.6.5.1).
In your example, the overriden Print(int x) is not a candidate and Print(double x) is applicable, so it is picked without a need to consider the methods in the base class.

The compiler looks at methods which are freshly-declared in the most derived class (based on the compile-time type of the expression) and sees if any are applicable. If they are, it uses the "best" one available.
See the answer to this question :
Different behaviour of method overloading in C#

Related

C#: Why isn't the expected override result coming out? [duplicate]

This question already has answers here:
new keyword in method signature
(9 answers)
Closed 9 years ago.
I have two classes
class A
{
public virtual void Metod1()
{
Console.WriteLine("A.Method1");
}
}
class B : A
{
public new void Metod1()
{
Console.WriteLine("B.Method1");
}
}
Then I write some code that declares instances of these classes, and calls their methods
static void Main(string[] args)
{
A a = new B();
a.Metod1();
B b = new B();
b.Metod1();
Console.ReadKey();
}
I gave following result:
A.Method1
B.Method1
But when I delete keyword new from signature method1 of class B and run Main method I got same result.
Question:Is new keyword in signature of methods only for better readability?
Edit:Are there cases where we can not do without a new keyword?
The new keyword let the code reader be aware that this method will hide the method with the same name in its base. Even if you ommited it, the compiler would treat it in the same way, but warn you about that.
Since you declared the method as virtual, you would get this warning when you compile:
'B.Metod1()' hides inherited member 'A.Metod1()'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword.
However, if you change the declaration by removing virtual as:
Declaration without virtual in A
class A {
public void Metod1() {
Console.WriteLine("A.Method1");
}
}
class B: A {
public void Metod1() {
Console.WriteLine("B.Method1");
}
}
Will still compile, but the warning message would be:
'B.Metod1()' hides inherited member 'A.Metod1()'. Use the new keyword if hiding was intended.
In either way as above, the following:
Test code
var b=new B();
b.Metod1();
(b as A).Metod1();
will output:
B.Method1
A.Method1
But, if you declare as the following:
Declaration with override in B
class A {
public virtual void Metod1() {
Console.WriteLine("A.Method1");
}
}
class B: A {
public override void Metod1() {
Console.WriteLine("B.Method1");
}
}
Then the output would be:
B.Method1
B.Method1
That is because Method1 of the base class is not just hidden but overridden by the derived class.
A case that you cannot just use new is that if Method1 is a abstract method in a abstract class:
Code that must use override in derived classes
abstract class A {
public abstract void Metod1();
}
class B: A {
public override void Metod1() { // use `new` instead of `override` would not compile
Console.WriteLine("B.Method1");
}
}
In this case you cannot just use new, because A requires derived classes to override Method1.
Knowing When to Use Override and New Keywords (C# Programming Guide)
In C#, a method in a derived class can have the same name as a method
in the base class. You can specify how the methods interact by using
the new and override keywords. The override modifier extends the base
class method, and the new modifier hides it.
also
By using new, you are asserting that you are aware that the member
that it modifies hides a member that is inherited from the base
class.
Yes, you are correct, it is for better readability in this situation.
But check carefully you should have a warning for not using new when hiding the base method.
You can read more here:
http://msdn.microsoft.com/en-us/library/vstudio/435f1dw2.aspx

C# - Is there a way to call a static method of a generic type in a class? [duplicate]

This question already has answers here:
Calling a static method on a generic type parameter
(9 answers)
Closed 3 years ago.
Example:
Public class a<T> where T: containsStatic
{
public void func()
{
T.StaticMethod();
}
}
Is it possible? And if not is there another way to do it?
EDIT:
it gives me the error: "'T' is a type parameter, which is not valid in the current context."
why is that? is there a way to fix this?
The problem I forsee with this is how do you guarantee that T supports StaticMethod?
However if you are sure that StaticMethod will always exist on T, you can use reflection to accomplish this fairly simply:
using System.Reflection;
public void func()
{
var staticMethod = typeof(T).GetMethod("StaticMethod", BindingFlags.Public | BindingFlags.Static);
staticMethod.Invoke(null, null);
}
Assume we wave a magic wand and you can do that now. Assume a type C:
public class C
{
public static void Foo()
{
}
}
How would this:
public class A<T> where T : C
{
public void Func()
{
T.Foo();
}
}
Be any different from:
public class A<T> where T : C
{
public void Func()
{
C.Foo();
}
}
It would not. It would have to be the same method being called. A static method call is generated statically (yeah, I know) when the method's code gets generated. The compiler seeing T.Foo() wouldn't possibly be able to insert any other call than C.Foo() there.
So you can't even express that in C#'s grammar, a type parameter is disallowed by the spec in such a context:
A type parameter cannot be used in a member access (Member access) or type name (Namespace and type names) to identify a static member or a nested type.
If you want to dynamically call a static method depending on T's value at runtime, refer to #Martin 's reflection solution.
You can call any static method, if it does not depend on the Generic Type.
If you have a class like
public class Test<T>
{
public static int Result => 5;
}
You can call
int n = Test<int>.Result;
at any place you want, and it is not important what type you actually insert, since any type will do the same
int n = Test<string[]>.Result;
will do the very same thing.
If your function depends on T like in
public class Test1<T>
{
public static void Action(T param)
{
}
}
You can use
Test1<int>.Action(8);
At any place you want.
Also inside other generic classes:
public class OtherClass<T>
{
public void Method(T param)
{
Test1<T>.Action(param);
}
}
But most often it is possible to write a generic function in a non-generic class like
public class Test2
{
public static void Action<T>(T param)
{
}
}
This works at any place in the Program
Test2.Action("string");
Test2.Action(9);
You can put this function in any class you want, since it's static. There is no need to put this function in a generic class.

Why is a cast to an `IEnumerable<T>` allowed but to a `List<T>` in a generic method [duplicate]

This question already has answers here:
Why can't I cast from a List<MyClass> to List<object>?
(6 answers)
Cannot convert from List<DerivedClass> to List<BaseClass>
(6 answers)
Closed 3 years ago.
I'm pretty sure I'm missing the obvious answer, but why this:
public static void Foo(IEnumerable<string> strings) { }
public static void Bar<T>(IEnumerable<T> ts)
{
Foo((IEnumerable<string>)ts);
}
is allowed, while this:
public static void Foo(List<string> strings) { }
public static void Bar<T>(List<T> ts)
{
Foo((List<string>)ts);
}
fails with CS0030 Cannot convert type 'System.Collections.Generic<T>' to type 'System.Collections.Generic<string>'.? Both have the potential to fail at runtime and both have the potential to succeed at runtime. What language rule governs this?
I think that this is an edge case example of the following question:
Cast List<T> to List<Interface>
I agree that in this case it seems weird because it's not possible to be casting up from something that extends string (the string class is sealed), but I'm guessing that the rule is just that you can't cast List<T> to List<SomethingElse> because the method might be called in a scenario where T is a class that extends the class SomethingElse or implements an interface called SomethingElse.
e.g.:
public static void Foo(List<string> strings) { }
public static void Bar<T>(List<T> ts)
{
Foo((List<MyInterface>)ts);
}
public static void OtherMethod1()
{
Bar<MyClass>(new List<MyClass>)
}
public static void OtherMethod2()
{
Bar<MyInterface>(new List<MyInterface>)
}
public classs MyClass : MyInterface
{
}
Therefore, because it is possible to write a method like OtherMethod1 that fails at runtime, the compiler doesn't allow this whole scenario.
Although, again, sealed classes appears to be a weird edge case that could possibly be allowed if Microsoft wanted to.

Difference between passing simple and reference parameters in Method Overloading and Overriding?

I have three classes:
public class A
{
}
public class B
{
void MethodA(ref A obj) { }
void MethodB(A obj) { }
}
public class C : B
{
void MethodA(ref A obj) { }
}
My first question : Are above methods are overloaded?
Second question : Difference between passing simple and refernce type objects as I know classes are reference type.
Third question : Is method in class C override method in class B ?
1: no; B.MethodA and C.MethodA are unrelated; the fact that they are implicitly private means it isn't even method-hiding
2: is not a question, but: pass-by-value vs pass-by-reference (the ref keyword) is largely orthogonal to value-type vs reference-type (struct vs class); it is a commonly misunderstood subject, but I can't really clarify without an actual question
3: no; the absence of any of virtual, override or abstract is the biggest clue

c# generic method overload not consistent with abstract Visitor pattern

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.

Categories

Resources