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

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

Related

Covariance Pattern for Abstract Classes

I'm realizing now that covariance is not available in abstract classes but is there anyway that I can utilize it here so that I can continue with this pattern.
Basically want the ability to create an instance of the first generic argument and pass the object which creates this object itself.
The below will fail at runtime because SpecialProcessor cannot be assigned to ProcessorBase with respect to generic types.
Appreciate any suggestions.
public class ProcessorUser<T> where T : ProcessorBase
{
public void ReceiveCommand()
{
Activator.CreateInstance(typeof (T), this);
}
}
public abstract class ProcessorBase
{
protected ProcessorBase(ProcessorUser<ProcessorBase> param)
{
}
}
public class SpecialProcessor : ProcessorBase
{
public SpecialProcessor(ProcessorUser<ProcessorBase> param)
: base(param)
{
}
}
Actually, from your less-than-complete code example, it's not clear at all a) what you are trying to do, and b) what "fails at runtime". You didn't show any code that calls the ReceiveCommand() method, so it's impossible to see in what way that code might fail.
That said, the usual way to gain access to variance in C# is through delegate or interface types. So you can declare a covariant interface to be implemented by ProcessorUser<T>, and then use that interface in the constructor declarations instead of the actual type. For example:
interface IProcessorUser<out T> where T : ProcessorBase
{
void ReceiveCommand();
}
class ProcessorUser<T> : IProcessorUser<T> where T : ProcessorBase
{
public void ReceiveCommand()
{
Activator.CreateInstance(typeof(T), this);
}
}
abstract class ProcessorBase
{
protected ProcessorBase(IProcessorUser<ProcessorBase> param)
{
}
}
class SpecialProcessor : ProcessorBase
{
private IProcessorUser<SpecialProcessor> _param;
public SpecialProcessor(IProcessorUser<SpecialProcessor> param)
: base(param)
{
_param = param;
}
public void ReceiveCommand() { _param.ReceiveCommand(); }
}
Note that I added the ReceiveCommand() method to the SpecialProcessor class just so I could see something execute at run-time. And that something does in fact work. But there's no way for me to know whether in your scenario, this is what you wanted to happen. You'd have to provide a good, minimal, complete code example that clearly shows what you are trying to do and what difficulty you are having doing it, if you want a clear, precise answer to that aspect of it.
(By the way, this really doesn't have anything to do with abstract classes. There's not even anything in your code example that is actually abstract, other than the class declaration itself, and the general principle applies to any class, not just abstract ones).

Overridden virtual method in C#

In "The C# Programming Language" book Eric Lippert mentioned this:
A subtle point here is that an overridden virtual method is still considered to be a method of the class that introduced it, and not a method of the class that overrides it.
What is the significance of this statement? Why does it matter if the overridden virtual method is considered to be a method of the class that introduced it (or otherwise) since the overridden method will never be called unless you are dealing with the derived class?
It matters when you have a reference of one type pointing to an object of a different type.
Example:
public class BaseClass {
public virtual int SomeVirtualMethod() { return 1; }
}
public class DerivedClass : BaseClass {
public override int SomeVirtualMethod() { return 2; }
}
BaseClass ref = new DerivedClass();
int test = ref.SomeVirtualMethod(); // will be 2
Because the virtual method is a member of the base class, you can call the overriding method with a reference of the base class type. If it wasn't, you would need a reference of the derived type to call the overriding method.
When you are shadowing a method instead of overriding it, the shadowing method is a member of the derived class. Depending on the type of the reference you will be calling the original method or the shadowing method:
public class BaseClass {
public int SomeMethod() { return 1; }
}
public class DerivedClass : BaseClass {
public new int SomeMethod() { return 2; }
}
BaseClass ref = new DerivedClass();
int test = ref.SomeMethod(); // will be 1
DerivedClass ref2 = ref;
int test2 = ref2.SomeMethod(); // will be 2
Here's the full quote from the book:
A subtle point here is that an overridden virtual method is still considered to be a method of the class that introduced it, and not a method of the class that overrides it. The overload resolution rules in some cases prefer members of more derived types to those in base types; overriding a method does not "move" where that method belongs in this hierarchy.
At the very beginning of this section, we noted that C# was designed with versioning in mind. This is one of those features that helps prevent "brittle base-class syndrome" from causing versioning problems.
The full quote makes it clear that Eric Lippert is talking specifically about method overloading, not just about how virtual methods work.
As an example, consider the following program:
class Base
{
public virtual void M2(int i) { }
}
class Derived : Base
{
public void M1(int i) { Console.WriteLine("Derived.M1(int)"); }
public void M1(float f) { Console.WriteLine("Derived.M1(float)"); }
public override void M2(int i) { Console.WriteLine("Derived.M2(int)"); }
public void M2(float f) { Console.WriteLine("Derived.M2(float)"); }
public static void Main()
{
Derived d = new Derived();
d.M1(1);
d.M2(1);
}
}
I think many developers would be surprised that the output is
Derived.M1(int)
Derived.M2(float)
Why would d.M2(1) invoke Derived.M2(float) even though Derived.M2(int) is a better match?
When the compiler is determining what the M1 in d.M1(1) refers to, the compiler sees that both M1(int) and M1(float) are introduced in Derived, so both overloads are applicable candidates. The compiler selects M1(int) over M1(float) as the best match for the integer argument 1.
When the compiler is determining what the M2 in d.M2(1) refers to, the compiler sees that M2(float) is introduced in Derived and is an applicable candidate. According to the overload resolution rules, "methods in a base class are not candidates if any method in a derived class is applicable". Because M2(float) is applicable, this rule prevents M2(int) from being a candidate. Even though M2(int) is a better match for the integer argument and even though it's overridden in Derived, it's still considered to be a method of Base.
Understanding that an overridden virtual method belongs to the class which introduces it, rather than the class that overrides it, makes it easier to understand the way class members are bound. Except when using dynamic objects, all bindings in C# are resolved at compile time. If a BaseClass declares a virtual method foo, and DerivedClass:BaseClass overrides foo, code which attempts to call foo on a variable of type BaseClass will always be bound to virtual method "slot" BaseClass.foo, which will in turn point to the actual DerivedClass.foo method.
This understanding can be especially important when dealing with generics, since in C#, unlike C++, members of generic types are bound according to the generics' constraints, rather than according to the concrete generic types. For example, suppose there were a SubDerivedClass:DerivedClass which created a new virtual method foo(), and one defined a method DoFoo<T>(T param) where T:BaseClass {param.foo();}. The param.foo() call would be bound to BaseClass.foo even if the method were invoked as DoFoo<SubDrivedClass>(subDerivedInstance). If the parameter were cast to SubDerivedClass before invoking foo, the call would be bound to SubDrivedClass.foo(), but the compiler can't tell when producing DoFoo<T> that T will be anything more specific than BaseClass, it can't bind to anything that doesn't exist in BaseClass.
Incidentally, there are times it would be useful if a class could simultaneously override a base-class member and create a new one; for example, given an abstract base class ReadableFoo with some abstract read-only property, it would be helpful if a class MutableFoo could both provide an override for that property and define a read-write property with the same name. Unfortunately, .net does not allow that. Given such a restriction, the best approach may be for ReadableFoo to provide a concrete non-virtual read-only property which calls an protected abstract method with a different name to get the value. That way, a derived class could shadow the read-only property with a read-write one (that would call the same virtual method for reading, or a new (possibly virtual) method for writing.
(following is untested)
class BaseClass
{
public virtual void foo() {Console.WriteLine("BaseClass.Foo");
}
class DerivedClass:BaseClass
{
public override void foo() {Console.WriteLine("Derived.Foo");
}
class SubDerivedClass:DerivedClass
{
public new virtual void foo() {Console.WriteLine("SubDerived.Foo");
}
class MegaDerivedClass:SubDerivedClass
{
public override void foo() {Console.WriteLine("MegaDerived.Foo");
}
void DoFoo1<T>(T param) where T:BaseClass
{
param.foo();
}
void DoFoo1<T>(T param) where T:SubDerivedClass
{
param.foo();
}
void test(void)
{
var megaDerivedInstance = new MegaDerivedClass();
DoFoo1<MegaDerivedClass>(megaDerivedInstance);
DoFoo2<MegaDerivedClass>(megaDerivedInstance);
}
A SubDerivedClass has two virtual foo() methods: BaseClass.foo() and SubDerivedClass.foo(). A MegaDerivedClass has those same two methods. Note that classes derived from SubDerivedClass() which attempt to override foo will override SubDerivedClass.foo() and will not affect BaseClass.foo(); with the declarations as above, no derivative of SubDerivedClass can override BaseClass.Foo. Note also that casting an instance of SubDerivedClass or a subclass thereof to DerivedClass or BaseClass will expose the BaseClass.foo virtual method for calling.
Incidentally, if the method declaration in SubDerivedClass had been friend new virtual void foo() {Console.WriteLine("SubDerived.Foo");, it would be impossible for other classes within the same assembly to override BaseClass.foo() (since any attempt to override foo() would override SubDerivedClass.foo()), but classes outside the assembly which derive from SubDerivedClass wouldn't see SubDerivedClass.foo() and could thus override BaseClass.foo().

Why does the C# compiler complain that "types may unify" when they derive from different base classes?

My current non-compiling code is similar to this:
public abstract class A { }
public class B { }
public class C : A { }
public interface IFoo<T>
{
void Handle(T item);
}
public class MyFoo<TA> : IFoo<TA>, IFoo<B>
where TA : A
{
public void Handle(TA a) { }
public void Handle(B b) { }
}
The C# compiler refuses to compile this, citing the following rule/error:
'MyProject.MyFoo<TA>' cannot implement both 'MyProject.IFoo<TA>' and 'MyProject.IFoo<MyProject.B>' because they may unify for some type parameter substitutions
I understand what this error means; if TA could be anything at all then it could technically also be a B which would introduce ambiguity over the two different Handle implementations.
But TA can't be anything. Based on the type hierarchy, TA can't be a B - at least, I don't think it can. TA must derive from A, which does not derive from B, and obviously there's no multiple class inheritance in C#/.NET.
If I remove the generic parameter and replace TA with C, or even A, it compiles.
So why do I get this error? Is it a bug in or general un-intelligence of the compiler, or is there something else I'm missing?
Is there any workaround or am I just going to have to re-implement the MyFoo generic class as a separate non-generic class for every single possible TA derived type?
This is a consequence of section 13.4.2 of the C# 4 specification, which states:
If any possible constructed type created from C would, after type arguments are substituted into L, cause two interfaces in L to be identical, then the declaration of C is invalid. Constraint declarations are not considered when determining all possible constructed types.
Note that second sentence there.
It is therefore not a bug in the compiler; the compiler is correct. One might argue that it is a flaw in the language specification.
Generally speaking, constraints are ignored in almost every situation in which a fact must be deduced about a generic type. Constraints are mostly used to determine the effective base class of a generic type parameter, and little else.
Unfortunately, that sometimes leads to situations where the language is unnecessarily strict, as you have discovered.
It is in general a bad code smell to implement "the same" interface twice, in some way distinguished only by generic type arguments. It is bizarre, for example, to have class C : IEnumerable<Turtle>, IEnumerable<Giraffe> -- what is C that it is both a sequence of turtles, and a sequence of giraffes, at the same time? Can you describe the actual thing you're trying to do here? There might be a better pattern to solve the real problem.
If in fact your interface is exactly as you describe:
interface IFoo<T>
{
void Handle(T t);
}
Then multiple inheritance of the interface presents another problem. You might reasonably decide to make this interface contravariant:
interface IFoo<in T>
{
void Handle(T t);
}
Now suppose you have
interface IABC {}
interface IDEF {}
interface IABCDEF : IABC, IDEF {}
And
class Danger : IFoo<IABC>, IFoo<IDEF>
{
void IFoo<IABC>.Handle(IABC x) {}
void IFoo<IDEF>.Handle(IDEF x) {}
}
And now things get really crazy...
IFoo<IABCDEF> crazy = new Danger();
crazy.Handle(null);
Which implementation of Handle gets called???
See this article and the comments for more thoughts on this issue:
http://blogs.msdn.com/b/ericlippert/archive/2007/11/09/covariance-and-contravariance-in-c-part-ten-dealing-with-ambiguity.aspx
Apparently it was by design as discussed at Microsoft Connect:
Allow to implement same generic interface for more that one type parameter in generic class under some conditions
And the workaround is, define another interface as:
public interface IIFoo<T> : IFoo<T>
{
}
Then implement this instead as:
public class MyFoo<TA> : IIFoo<TA>, IFoo<B>
where TA : A
{
public void Handle(TA a) { }
public void Handle(B b) { }
}
It now compiles fine, by mono.
You can sneak it under the radar if you put one interface on a base class.
public interface IFoo<T>
{
}
public class Foo<T> : IFoo<T>
{
}
public class Foo<T1, T2> : Foo<T1>, IFoo<T2>
{
}
I suspect this works because if the types do "unify" it is clear the derived class's implementation wins.
See my reply to basically the same question here:
https://stackoverflow.com/a/12361409/471129
To some extent, this can be done! I use a differentiating method, instead of qualifier(s) limiting the types.
It does not unify, in fact it might be better than if it did because you can tease the separate interfaces apart.
See my post here, with a fully working example in another context.
https://stackoverflow.com/a/12361409/471129
Basically, what you do is add another type parameter to IIndexer, so that it become IIndexer <TKey, TValue, TDifferentiator>.
Then you when you use it twice, you pass "First" to the 1st use, and "Second" for the 2nd use
So, class Test becomes: class Test<TKey, TValue> : IIndexer<TKey, TValue, First>, IIndexer<TValue, TKey, Second>
Thus, you can do new Test<int,int>()
where First, and Second are trivial:
interface First { }
interface Second { }
Taking a guess now...
Couldn't A, B and C be declared in outside assemblies, where the type hierarchy may change after the compilation of MyFoo<T>, bringing havoc into the world?
The easy workaround is just to implement Handle(A) instead of Handle(TA) (and use IFoo<A> instead of IFoo<TA>). You cant do much more with Handle(TA) than access methods from A (due to the A : TA constraint) anyway.
public class MyFoo : IFoo<A>, IFoo<B> {
public void Handle(A a) { }
public void Handle(B b) { }
}
Hmm, what about this:
public class MyFoo<TA> : IFoo<TA>, IFoo<B>
where TA : A
{
void IFoo<TA>.Handle(TA a) { }
void IFoo<B>.Handle(B b) { }
}
I know it has been a while since the thread was posted but for those who come down to this thread via the search engine for help. Note that 'Base' stands for base class for TA and B in below.
public class MyFoo<TA> : IFoo<Base> where TA : Base where B : Base
{
public void Handle(Base obj)
{
if(obj is TA) { // TA specific codes or calls }
else if(obj is B) { // B specific codes or calls }
}
}

C# interface cannot contain operators

Can anyone please explain why C# interfaces are not allowed to contain operators?
Thanks.
C# operators have to be static. Interfaces, by definition, apply to instances. There is no mechanism to require a type to implement static members.
EDIT:
Since C# 8.0, as you can see here, it is now possible to define local methods in interfaces and implement them within the interface itself, e.g. allowing to create method overloads without requiring implementations to care about those overloads as well, when they might just supply an additional parameter to the overload that has to be implemented.
Along with this, you can also define operators within interfaces, though they must be static and so they must be implemented in the interface.
So in C# 8.0 this will print "this works in C# 8" followed by "1":
interface ICanAdd
{
int Value { get; }
public static int operator+ (ICanAdd lvalue, int rvalue)
{
Console.WriteLine("this works in C# 8");
return lvalue.Value + rvalue;
}
}
class Add : ICanAdd
{
public int Value => 0;
}
class Program
{
static void Main(string[] args)
{
ICanAdd foo = new Add();
var x = foo + 1;
Console.WriteLine(x);
}
}
Edit 2020-01-23
You cannot add conversion, equality or inequality operators to interfaces, otherwise you'll hit the following error:
CS0567 C# Interfaces cannot contain conversion, equality, or inequality operators
You can't define operators on interfaces because a class can implement multiple interfaces. Imagine if this code were possible:
static class Fooness {
public static operator==(IFoo l, IFoo r) { ... }
}
static class Barness {
public static operator==(IBar l, IBar r) { ... }
}
public class Foobar : IFoo, IBar { ... }
Which == implementation should prevail if used on instances of Foobar? (And before you answer, imagine if IFoo/Fooness come from one DLL and IBar/Barness comes from another).
Even if you could somehow resolve that ambiguity, we should ask ourselves whether it would even be a good idea. I hope the above shows that with operator== it's a seriously bad idea. The author of the per-interface == operator presumes that the only important aspects of an object when it comes to comparison are those encompassed by the interface. Sometimes that can be true, but it's not generally true.
That's why it's prudent to only use operators on sealed classes. Only then can you be sure that your operator knows enough about the object to work correctly.
If your method could not be properly implemented on the interface, you can make a call to a self method that will be overriden by the derived class:
public interface INotification
{
INotification Combine(INotification b);
public static INotification operator +(INotification a, INotification b)
{
return a.Combine(b);
}
}
Derived class:
public class Notification : INotification
{
public INotification Combine(INotification b)
{
_events.AddRange(b.Events);
_logs.AddRange(b.Logs);
ValidationResult.Errors.AddRange(b.GetValidationErrors());
return this;
}
public static Notification operator +(Notification a, Notification b)
{
a._events.AddRange(b.Events);
a._logs.AddRange(b.Logs);
a.ValidationResult += b.ValidationResult;
return a;
}
}

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