I have the following simple code
abstract class A
{
public abstract void Test(Int32 value);
}
class B : A
{
public override void Test(Int32 value)
{
Console.WriteLine("Int32");
}
public void Test(Double value)
{
Test((Int32)1);
}
}
When I ran this code the line Test((Int32)1) causes stack overflow due to infinite recursion. The only possible way to correctly call proper method (with integer parameter) I found is
(this as A).Test(1);
But this is not appropriate for me, because both methods Test are public and I am willing the users to be able to call both method?
Method overload resolution in C# does not always behave as you might expect, but your code is behaving according to the specification (I wrote a blog post about this a while ago).
In short, the compiler start off by finding methods that
Has the same name (in your case Test)
are declared in the type (in your case B) or one of its base types
are not declared with the override modifier
Note that last point. This is actually logical, since virtual methods are resolved in run-time, not compile time.
Finally, if the type (in this case B) has a method that is a candidate (which means that the parameters in your call can be implicitly converted to the parameter type of the candidate method), that method will be used. Your overridden method is not even part of the decision process.
If you want to call your overridden method, you will need to cast the object to its base type first.
Unfortunately in order to call the A::Test(int) through a B reference some sort of cast is needed. So long as the C# compiler sees the reference through B it will pick the B::Test(double) version.
A slightly less ugly version is the following
((A)this).Test(1);
Another thought though is have a private method with a different name that both feed into.
class B : A {
public override void Test(int i) {
TestCore(i);
}
public void Test(double d) {
TestCore(1);
}
private void TestCore(int i) {
// Combined logic here
}
}
Related
namespace test
{
class Program
{
static void Main(string[] args)
{
Derived obj = new Derived();
int i = 10;
obj.Foo(i);
Console.ReadLine();
}
}
class Base
{
public virtual void Foo(int i)
{
Console.WriteLine("Base:Foo()");
}
}
class Derived:Base
{
public override void Foo(int i)
{
Console.WriteLine("Foo(int)");
}
public void Foo(object i)
{
Console.WriteLine("Foo(object)");
}
}
}
output of the program according to me should be Foo(int) but output is coming as Foo(object) please help me in understanding the diffrence in output
Good question, I can reproduce your results. If one takes a look at the C# specifications one will find the following snippets:
7.5.3 Overload resolution
For example, 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).
7.4 Member Lookup
Otherwise, the set consists of all accessible (§3.5) members named N
in T, including inherited members and the accessible members named N
in object. If T is a constructed type, the set of members is obtained
by substituting type arguments as described in §10.3.2. Members that
include an override modifier are excluded from the set.
7.6.5.1 Method invocations
The set of candidate methods is reduced to contain only methods from
the most derived types: For each method C.F in the set, where C is the
type in which the method F is declared, all methods declared in a base
type of C are removed from the set. Furthermore, if C is a class type
other than object, all methods declared in an interface type are
removed from the set.
Sounds a bit complicated? Even the C# designers seem to think so and put in the 'helpful' note:
7.6.5.1 Method invocations
The intuitive effect of the resolution rules described above is as
follows: To locate the particular method invoked by a method
invocation, start with the type indicated by the method invocation and
proceed up the inheritance chain until at least one applicable,
accessible, non-override method declaration is found. Then perform
type inference and overload resolution on the set of applicable,
accessible, non-override methods declared in that type and invoke the
method thus selected. If no method was found, try instead to process
the invocation as an extension method invocation.
If we take a look at your derived class, we see two possible methods for C# to use:
A) public override void Foo(int i)
B) public void Foo(object i)
Let's use that last checklist!
Applicability - Both A and B are applicable -(both are void, both are named 'Foo' and both can accept an integer value).
Accessibility - Both A and B are accessible (public)
Not Overridden - Only B is not overridden.
But wait you might say! A is more specific than B!
Correct, but that consideration is only made after we've disregarded option A. As Eric Lippert (one of the designers) puts it Closer is always better than farther away. (Thanks Anthony Pegram)
Addendum
There is always the 'new' keyword:
class Derived : Base
{
public new void Foo(int i)
{
Console.WriteLine("Foo(int)");
}
public void Foo(object i)
{
Console.WriteLine("Foo(object)");
}
}
Though the specifics of that best left for another question!
The simple datatype int descends from object. You are overriding the function and also overloading the parameter list. Since the function name is the same with a different signature the compiler allows this. For simple objects, I image one copy of the parameter signature in the most basic form is stored in the method table.
I have a class that overrides the addition operator twice. One that takes the type parameter and one that takes a double:
public class A<T>
{
public A() { }
public static A<T> operator +(A<T> a, T t)
{
Console.WriteLine("Generic add called.");
return new A<T>(); // return to keep the compiler happy
}
public static A<T> operator +(A<T> a, double d)
{
Console.WriteLine("Double add called.");
return new A<T>(); // return to keep the compiler happy
}
}
When the class is parameterized by the int type, it behaves as expected:
A<int> aInt = new A<int>();
var test = aInt + 3;
// -> Generic add called.
test = aInt + 3.0;
// -> Double add called.
But when parameterized by the double type, the non-generic add is called:
A<double> aDouble = new A<double>();
var otherTest = aDouble + 3.0;
// -> Double add called.
Assuming this behavior is the norm, I know which will be called. The non-generic override will be preferred. That said...
Will the non-generic method be always be preferred in the event of a collision?
All of the above code is available, runnable in your browser, here
EDIT: This question is related, but it's asking about generic methods, not classes. He gives this code:
class A
{
public static void MyMethod<T>(T myVal) { }
public static void MyMethod(int myVal) { }
}
which does not apply to my usage examples. Distinguishing between a.MyMethod(3) and a.MyMethod<int>(3) is obvious - one is generic and one is not.
The more specific method will be chosen, but that construction is a bad idea because it is technically unspecified behaviour.
To quote #EricLippert, substituting the code snippets for the ones from my question:
But the situation with [aDouble + 3.0] is far worse. The CLR rules make this sort of situation "implementation defined behaviour" and therefore any old thing can happen. Technically, the CLR could refuse to verify a program that constructs type [A<double>]. Or it could crash. In point of fact it does neither; it does the best it can with the bad situation.
Are there any examples of this sort of type construction causing truly implementation-defined behaviour?
Yes. See these articles for details:
http://blogs.msdn.com/b/ericlippert/archive/2006/04/05/odious-ambiguous-overloads-part-one.aspx
http://blogs.msdn.com/b/ericlippert/archive/2006/04/06/odious-ambiguous-overloads-part-two.aspx
Simple answering yes. The compiler assume that because you have treated by hand a particular type parameter, that means that it has some special logic for you. That's why the second operator is called. To say further, operators are nothing more than static methods that accepts some parameters. For your case it's a binary operator so the static method has two parameters.
I write this piece of code in one of my C# project:
public static class GetAppendReceiver
{
public static AppendReceiver<DataType> Get<DataType>(AppendReceiver<DataType>.DataProcessor processor0, int delayIn = 0)
{
throw new InvalidOperationException();
}
public static AppendReceiver<string> Get(AppendReceiver<string>.DataProcessor processor0, int delayIn = 0)
{
return new StringAppendReceiver(processor0, delayIn);
}
}
public abstract class AppendReceiver<DataType>
{
public delegate void DataProcessor(DataType data);
...
}
AppendReceiver<DataType> is an Abstract class, DataProcessor is a delegate type.
When calling GetAppendReceiver.Get with a string DataProcessor I expect the overloaded function to be called, but I get the InvalidOperationException.
Here is my call:
class ClassA<DataType>
{
public void RegisterAppendReceiver(AppendReceiver<DataType>.DataProcessor receiver)
{
appendReceivers.Add(GetAppendReceiver.Get(receiver, Delay));
}
}
Example of RegisterAppendReceiver call:
myObject.RegisterAppendReceiver(myMethod);
Where myMethod is defined like this:
public void writeMessage(string strMessageIn)
My question is why I get the wrong overload called, and how can I force the language to call the overload I want ?
Thanks for your help !
Eric Lippert answers this question concisely in his article Generics are not Templates
I don't want to copy the entire article. So the relevant point is this:
We do the overload resolution once and bake in the result.
So the C# compiler decides, at the time it compiles RegisterAppendReceiver, which overload of "GetAppendReceiver.Get" it is going to call. Since, at that point, the only thing it knows about DataType is that DataType can be anything at all, it compiles in the call to the overload that takes an AppendReceiver.DataProcessor, not an AppendReceiver.DataProcessor.
By comparison, the C++ compiler does not behave this way. Each and every time a generic call is made, the compiler does the substitution over again. This is one reason C++ compilers are much slower than C# compilers.
C# allows the use of optional parameters: one can specify the value in case the parameter is omitted in a call and the compiler then specifies the value itself.
Example:
public interface IFoo {
void SomeMethod (int para = 0);
}
This idea is useful but a problem is that one can define several "default values" on different levels of the class hierarchy. Example:
public class SubFoo : IFoo {
public void SomeMethod (int para = 1) {
//do something
}
}
If one later calls:
SubFoo sf = new SubFoo ();
sf.SomeMethod ();
Foo f = sf;
f.SomeMethod ();
The result is that the first call is done with para equal to 1 and the second with para equal to 0 (as interface). This make sense since the compiler adds the default values and in the first case the this is a SubFoo thus the default value is 1.
It is of course up to the programmer to maintain consistency, but such schizophrenic situations can easily occur when a programmer changes his/her mind in the middle of the process and forgets to modify all default values.
Problematic is that the compiler doesn't warn that different default values are in use whereas this can be checked by moving up the class hierarchy. Furthmore some people might mimic default parameters with:
public class SubFoo2 {
public virtual void SomeMethod () {
SomeMethod(1);
}
public void SomeMethod (int para) {
//do something
}
}
Which allows dynamic binding and thus overriding consistently. It thus requires one to be very careful with how default values are "implemented".
Are there ways to enforce (with compiler flags for instance) to check whether the default values are consistent? If not it would be nice to have at least a warning that something is not really consistent.
Well not necessary compile-time solution - but you can make unit test for that (I suspect that you're taking seriously unit testing and you run them frequently if you ask this kind of question). The idea is to create assertion method like AssertThatDefaultParametersAreEqual(Type forType) - find all classes that are not abstract (using reflection) and inherit from forType then iterate over all methods which have defined default parameters:
MethodInfo[] methodInfo = Type.GetType(classType).GetMethods(BindingFlags.OptionalParamBinding | BindingFlags.Invoke);
Group them by MethodInfo.Name and check does within the group all same parameters with default values (could be obtained by MethodInfo.GetParameters().Where(x => x.IsOptional)) have the equal property of ParameterInfo.DefaultValue.
edit: btw. that might not work in Mono because compilers aren't obligated to emit for instance: Optional BindingFlag.
If you want to have a compile time indication that a method is changing the default value of an optional argument, you're going to need to use some sort of 3rd party code analysis tool, as C# itself doesn't provide any means of providing such a restriction, or any warnings when its done.
As a workaround, one option is to avoid using optional parameter values and instead use multiple overloads. Since you have an interface here, that would mean using an extension method so that the implementation of the overload with a default value is still defined in the general case:
public interface IFoo
{
void SomeMethod(int para);
}
public static class FooExtensions
{
public static void SomeMethod(this IFoo foo)
{
foo.SomeMethod(0);
}
}
So while this approach does technically still allow someone to create an extension (or instance) method named SomeMethod and accepting no int argument, it would mean that someone would really need to go out of their way to actively change the "default value". It doesn't require implementations of the interface to supply the default value, which risks them unintentionally providing the wrong default value.
Define const int DefaultPara = 1; and then use that instead of hard coding numerical values.
interface IFoo
{
void SomeMethod (int para = DefaultPara);
}
public class SubFoo : IFoo {
public void SomeMethod (int para = DefaultPara) {
//do something
}
}
class foo
{
public void bar(int i) { ... };
public void bar(long i) { ... };
}
foo.bar(10);
I would expect this code to give me some error, or at least an warning, but not so...
What version of bar() is called, and why?
The int version of bar is being called, because 10 is an int literal and the compiler will look for the method which closest matches the input variable(s). To call the long version, you'll need to specify a long literal like so: foo.bar(10L);
Here is a post by Eric Lippert on much more complicated versions of method overloading. I'd try and explain it, but he does a much better job and I ever could: http://blogs.msdn.com/b/ericlippert/archive/2006/04/05/odious-ambiguous-overloads-part-one.aspx
from the C# 4.0 Specification:
Method overloading permits multiple
methods in the same class to have the
same name as long as they have unique
signatures. When compiling an
invocation of an overloaded method,
the compiler uses overload resolution
to determine the specific method to
invoke. Overload resolution finds the
one method that best matches the
arguments or reports an error if no
single best match can be found. The
following example shows overload
resolution in effect. The comment for
each invocation in the Main method
shows which method is actually
invoked.
class Test {
static void F() {
Console.WriteLine("F()");
}
static void F(object x) {
Console.WriteLine("F(object)");
}
static void F(int x) {
Console.WriteLine("F(int)");
}
static void F(double x) {
Console.WriteLine("F(double)");
}
static void F<T>(T x) {
Console.WriteLine("F<T>(T)");
}
static void F(double x, double y) {
Console.WriteLine("F(double,double)");
}
static void Main() {
F(); // Invokes F()
F(1); // Invokes F(int)
F(1.0); // Invokes F(double)
F("abc"); // Invokes F(object)
F((double)1); // Invokes F(double)
F((object)1); // Invokes F(object)
F<int>(1); // Invokes F<T>(T)
F(1, 1); // Invokes F(double, double)
}
}
As shown by the example, a particular
method can always be selected by
explicitly casting the arguments to
the exact parameter types and/or
explicitly supplying type arguments.
As Kevin says, there's an overload resolution process in place. The basic sketch of the process is:
Identify all the accessible candidate methods, possibly using type inference on generic methods
Filter out the inapplicable methods; that is, the methods that cannot work because the arguments don't convert implicitly to the parameter types.
Once we have a set of applicable candidates, run more filters on them to determine the unique best one.
The filters are pretty complicated. For example, a method originally declared in a more derived type is always better than a method originally declared in a less derived type. A method where the argument types exactly match the parameter types is better than one where there are inexact matches. And so on. See the specification for the exact rules.
In your particular example the "betterness" algorithm is straightforward. The exact match of int to int is better than the inexact match of int to long.
I would say if you exceed below limit
-2,147,483,648 to 2,147,483,647
control will go to long
Range for long
–9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
Max value for int
foo.bar(-2147483648);
or
foo.bar(2147483648);
Long will get control if we exceed the value by 2147483648