why is this generic not resolved at compile time? - c#

I have the following code. I expect it to print:
A
B
C
DONE
instead it prints
P
P
P
DONE
why?
UPDATE
I'm not asking for a work around solution. I want to know why this is happening. I thought generics were resolved at compile time. From what I can tell it should be able to resolve these to the proper methods at compile time, but apparently it is not and I do not understand why. I am looking for an explanation of why, not a work around solution.
here is the code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication50
{
class Parent
{
public string FieldName { get; set; }
public string Id { get; set; }
}
class ChildA : Parent
{
public string FieldValue { get; set; }
}
class ChildB : Parent
{
public DateTime? Start { get; set; }
public DateTime? End { get; set; }
}
class ChildC : Parent
{
public ICollection<string> Values { get; set; }
}
class Program
{
void Validate<T>(Parent item) where T : Parent
{
if (item is T)
Validate(item as T);
}
void Validate(ChildA filter)
{
Console.WriteLine("A");
}
void Validate(ChildB filter)
{
Console.WriteLine("B");
}
void Validate(ChildC filter)
{
Console.WriteLine("C");
}
void Validate(Parent filter)
{
Console.WriteLine("P");
// do nothing placeholder so the code will compile
}
ArgumentException Fail(Parent filter, string message)
{
return new ArgumentException(message, filter.FieldName);
}
void Run()
{
var list = new List<Parent> {
new ChildA(), new ChildB(), new ChildC() };
Validate<ChildA>(list[0]);
Validate<ChildB>(list[1]);
Validate<ChildC>(list[2]);
}
public static void Main()
{
new Program().Run();
Console.WriteLine();
Console.WriteLine("DONE");
Console.ReadLine();
}
}
}

Generics are a run-time concept. This is their primary difference from C++ templates, which are a compile-time concept.
Within the method Validate<T>, T is always unknown at compile-time, even when explicitly specified by the caller. The only thing Validate<T> knows about T is that it descends from Parent.
More specifically, generics cannot be used to generate code. What you're trying would work under C++ because when C++ sees a call to Validate<ClassA>, it actually recompiles Validate<T>, so templates become a kind of code generation. Under C#, Validate<T> is only compiled once, so generics cannot be used as a kind of code generation.
Under C++, the call to Validate<ClassA> will instantiate the template at compile-time.
Under C#, the call to Validate<ClassA> will instatiate the generic method at run-time.

Overload resolution is performed at compile-time, not at runtime.
The usual solution is to use simple virtual dispatch here:
class Parent
{
public virtual void Validate() { Console.WriteLine("P"); }
}
class ChildA : Parent
{
public override void Validate() { Console.WriteLine("A"); }
}
class ChildB : Parent
{
public override void Validate() { Console.WriteLine("B"); }
}
void Run()
{
var list = new List<Parent> { new ChildA(), new ChildB() };
list[0].Validate(); // prints "A"
list[1].Validate(); // prints "B"
}

The item will ALWAYS be validated as type Parent.
The idea behind generics is that you do NOT have type specific code.. hence the "generic" part of it.
You are limiting to a branch of classes, in this case Parent and everything that descends from it. This means the code should execute as if the object being passed in was of type Parent.
As dtb said, the Visitor pattern could apply here.
Another idea would be to simply have an interface which defined the Validate() method that each class had to support. I think this would be a better route to take.

Assuming you can use C# 4.0, you can defeat the static overload resolution that the C# compiler will do by using the "dynamic" keyword. Simply change your validate function to:
void Validate<T>(Parent item) where T : Parent
{
dynamic dyn = item;
if (item is T)
Validate(dyn);
}
and the output will be:
C:\tmp>temp.exe
A
B
C
DONE
I just learned this myself from #juharr's link to Eric Lippert's blog. Read more about the dynamic type on msdn.

Related

.NET Extension methods on constructed types

I was experimenting in order to create a little compile-safe helper for mapping between classes.
public class A : IMappableTo<B>, IMappableTo<A>
{
public string Name { get; set; }
}
public class B
{
public string Name { get; set; }
}
public interface IMappableTo<T>
{
}
public static class ExtensionTest
{
public static T MapTo<T>(this IMappableTo<T> source)
{
return default(T); // this does not mind, just for demo purposes
}
}
The intent was to create an extension method able to detect not implemented maps (at compile time).
It worked as expected, but with an unexpected issue.
public static void test()
{
// compiler doesn't complain, but intellisense can't autocomplete it.
var case1 = new A().MapTo<A>().MapTo<B>();
var case2 = new A().MapTo<string>(); // compiler complains, as intended
}
So well, it does compile and work, but Visual Studio (tested with 2015/2017) is unable to autocomplete the extension method. I did some additional tests and it seems to be produced by the fact that class A implements two IMappableTo constructed interfaces. If I remove one, the autocomplete simply works again.
Any idea of how to fix this behaviour or rewrite the code in a manner that cause no further troubles?

Down-cast ComponentRegistration to non-generic type

I`m using Castle.Windsor library, and what i want is to get "Implementation" property, from all items in IRegistration[].
I have following interfaces and classes:
public interface IA
{
int a { get; set; }
}
public class A : IA
{
public int a { get; set; }
}
public interface IB
{
int b { get; set; }
}
public class B : IB
{
public int b { get; set; }
}
And a static class which contains this Components:
public static class Bootekstraperek
{
private static readonly IRegistration[] _commonRegistrations =
{
Component.For<IA>().ImplementedBy<A>(),
Component.For<IB>().ImplementedBy<B>()
};
public static void Test()
{
List<IRegistration> list = _commonRegistrations.ToList();
foreach (var registration in list)
{
ComponentRegistration a = registration as ComponentRegistration;
Console.WriteLine(a.Implementation.FullName);
}
}
}
And of course variable a is null after every iteration.
It works only when i cast to Generic ComponentRegistration
var a = registration as ComponentRegistration<A>;
But, that dont helps me if i have too much different components inside this array. So Switch statement is not an option.
I have tried using reflections, but i still didn`t managed to properly cast.
How can i achieve what i want With or Without using reflections?
thxia.
This is not easy because the IRegistration API was never meant to be used in this way.
So my answer has two parts.
How you can do it. Use dynamic.
you only need to change a small bit of your code:
foreach (dynamic registration in list)
{
Console.WriteLine(registration.Implementation.FullName);
}
What is the underlying goal you're trying to achieve here? Have a look at Windsor's diagnostics if your goal is to keep a level of visibility into what gets registered, how and be on a lookout for potential issues.
A small amount of Reflection solves the problem (it is a small amount, but it looks verbose, because Reflection):
foreach (var registration in list)
{
Console.WriteLine(
((Type)registration.GetType().GetProperty(
"Implementation"
).GetGetMethod().Invoke(
registration,new object[] { })
).FullName);
}
Since you won't know the types that are being used as generic type parameters until runtime, I don't think there's a way to do this without any Reflection.
The above assumes that all of the registrations will be ComponentRegistration<T> objects of some sort. If that's an unsafe assumption, there may be some other implementations of IRegistration that don't implement an Implementation property or it may not be publicly accessible - so insert appropriate interim error checking if that's the case.

How to handle a collection of Foo<T>, where T can be different for each item?

Problem description
I am trying to store a collection of generic Foo<T> elements, where T may be different for each item. I also have functions like DoSomething<T>(Foo<T>) that can accept a Foo<T> of any T. It seems like I should be able to call this function on each element of the abovementioned list, because they are all valid parameters for the function, but I can't seem to express this idea to the C# compiler.
The problem, as far as I can tell, is that I can't really express a list like that, because C# does not allow me to write Foo<T> without binding T. What I would want is something like Java's wildcard mechanism (Foo<?>). Here is how it might look in a Pseudo-C#, where this wildcard type existed:
class Foo<T> {
// ...
}
static class Functions {
public static void DoSomething<T>(Foo<T> foo) {
// ...
}
public static void DoSomething(List<Foo<?>> list) {
foreach(Foo<?> item in list)
DoSomething(item);
}
}
This pattern is valid in Java, but how can I do the same in C#? I have experimented a bit to find solutions which I'll post in an answer below, but I feel that there should be a better way.
Note: I have already solved this problem "well enough" for my practical needs, and I know ways to work around it (e.g. using the dynamic type), but I'd really like to see if there is a simpler solution that does not abandon static type safety.
Just using object or a nongeneric supertype, as has been suggested below, does not allow me to call functions that require a Foo<T>. However, this can be sensible even if I don't know anything about T. For example, I could use the Foo<T> to retrieve a List<T> list from somewhere, and a T value from somewhere else, and then call list.Add(value) and the compiler will know that all the types work out right.
Motivation
I was asked why I would ever need something like this, so I'm making up an example that is a bit closer to the everyday experience of most developers. Imagine that you are writing a bunch of UI components which allow the user to manipulate values of a certain type:
public interface IUiComponent<T> {
T Value { get; set; }
}
public class TextBox : IUiComponent<string> {
public string Value { get; set; }
}
public class DatePicker : IUiComponent<DateTime> {
public DateTime Value { get; set; }
}
Apart from the Value property, the components will have have many other members of course (e.g. OnChange events).
Now let's add an undo system. We shouldn't have to modify the UI elements themselves for this, because we have access to all the relevant data already--Just hook up the OnChange events and whenever the user changes a UI component, we store away the value of each IUiComponent<T> (A bit wasteful, but let's keep things simple). To store the values we will use a Stack<T> for each IUiComponent<T> in our form. Those lists are accessed by using the IUiComponent<T> as key. I'll leave out the details of how the lists are stored (If you think this matters I'll provide an implementation).
public class UndoEnabledForm {
public Stack<T> GetUndoStack<T>(IUiComponent<T> component) {
// Implementation left as an exercise to the reader :P
}
// Undo for ONE element. Note that this works and is typesafe,
// even though we don't know anything about T...
private void Undo<T>(IUiComponent<T> component) {
component.Value = GetHistory(component).Pop();
}
// ...but how do we implement undoing ALL components?
// Using Pseudo-C# once more:
public void Undo(List<IUiComponent<?>> components) {
foreach(IUiComponent<?> component in components)
Undo(component);
}
}
We could undo everything by directly calling Undo<T>() on all the IUiComponents (by name):
public void Undo(List<IUiComponent<?>> components) {
Undo(m_TextBox);
Undo(m_DatePicker);
// ...
}
However, I want to avoid this, because it means you will have to touch one more place in the code if you add/remove a component. If you have tens of fields and more functions that you want to perform on all the components (e.g. write all their values to a database and retrieve them again), this can become a lot of duplication.
Sample Code
Here is a small piece of code that you can use to develop/check a solution. The task is to put several Pair<T>-objects into some kind of collection object, and then call a function which accepts this collection object and swaps the First and Second field of each Pair<T> (using Application.Swap()). Ideally, you should not use any casts or reflection. Bonus points if you can manage to do it without modifying the Pair<T>-class in any way :)
class Pair<T> {
public T First, Second;
public override string ToString() {
return String.Format("({0},{1})", First, Second);
}
}
static class Application {
static void Swap<T>(Pair<T> pair) {
T temp = pair.First;
pair.First = pair.Second;
pair.Second = temp;
}
static void Main() {
Pair<int> pair1 = new Pair<int> { First = 1, Second = 2 };
Pair<string> pair2 = new Pair<string> { First = "first", Second = "second" };
// imagine more pairs here
// Silly solution
Swap(pair1);
Swap(pair2);
// Check result
Console.WriteLine(pair1);
Console.WriteLine(pair2);
Console.ReadLine();
}
}
I would suggest you define an interface to invoke the functions you'll want to call as DoSomething<T>(T param). In simplest form:
public interface IDoSomething
{ void DoSomething<T>(T param); }
Next define a base type ElementThatCanDoSomething:
abstract public class ElementThatCanDoSomething
{ abstract public void DoIt(IDoSomething action); }
and a generic concrete type:
public class ElementThatCanDoSomething><T>
{
T data;
ElementThatCanDoSomething(T dat) { data = dat; }
override public void DoIt(IDoSomething action)
{ action.DoIt<T>(data); }
}
Now it's possible to construct an element for any type compile-time T, and pass that element to a generic method, keeping type T (even if the element is null, or if the element is of a derivative of T). The exact implementation above isn't terribly useful, but it can be easily extended in many useful ways. For example, if type T had generic constraints in the interface and concrete type, the elements could be passed to methods which had those constraints on its parameter type (something which is otherwise very difficult, even with Reflection). It may also be useful to add versions of the interface and invoker methods that can accept pass-through parameters:
public interface IDoSomething<TX1>
{ void DoSomething<T>(T param, ref TX1 xparam1); }
... and within the ElementThatCanToSomething
abstract public void DoIt<TX1>(IDoSomething<TX1> action, ref TX1 xparam1);
... and within the ElementThatCanToSomething<T>
override public void DoIt<TX1>(IDoSomething<TX1> action, ref TX1 xparam1)
{ action.DoIt<T>(data, ref xparam1); }
The pattern may easily be extended to any number of pass-through parameters.
EDIT 2: in the case of your overhauled question, the approach is basically the same I've proposed you earlier.
Here I'm adapting it to your scenario and commenting better on what makes it work (plus an unfortunate "gotcha" with value types...)
// note how IPair<T> is covariant with T (the "out" keyword)
public interface IPair<out T> {
T First {get;}
T Second {get;}
}
// I get no bonus points... I've had to touch Pair to add the interface
// note that you can't make classes covariant or contravariant, so I
// could not just declare Pair<out T> but had to do it through the interface
public class Pair<T> : IPair<T> {
public T First {get; set;}
public T Second {get; set;}
// overriding ToString is not strictly needed...
// it's just to "prettify" the output of Console.WriteLine
public override string ToString() {
return String.Format("({0},{1})", First, Second);
}
}
public static class Application {
// Swap now works with IPairs, but is fully generic, type safe
// and contains no casts
public static IPair<T> Swap<T>(IPair<T> pair) {
return new Pair<T>{First=pair.Second, Second=pair.First};
}
// as IPair is immutable, it can only swapped in place by
// creating a new one and assigning it to a ref
public static void SwapInPlace<T>(ref IPair<T> pair) {
pair = new Pair<T>{First=pair.Second, Second=pair.First};
}
// now SwapAll works, but only with Array, not with List
// (my understanding is that while the Array's indexer returns
// a reference to the actual element, List's indexer only returns
// a copy of its value, so it can't be switched in place
public static void SwapAll(IPair<object>[] pairs) {
for(int i=0; i < pairs.Length; i++) {
SwapInPlace(ref pairs[i]);
}
}
}
That's more or less it... Now in your main you can do:
var pairs = new IPair<object>[] {
new Pair<string>{First="a", Second="b"},
new Pair<Uri> {
First=new Uri("http://www.site1.com"),
Second=new Uri("http://www.site2.com")},
new Pair<object>{First=1, Second=2}
};
Application.SwapAll(pairs);
foreach(var p in pairs) Console.WriteLine(p.ToString());
OUTPUT:
(b,a)
(http://www.site2.com/,http://www.site1.com/)
(2,1)
So, your Array is type-safe, because it can only contain Pairs (well, IPairs). The only gotcha is with value types. As you can see I had to declare the last element of the array as a Pair<object> instead of Pair<int> as I would have liked.
This is because covariance/contravariance don't work with value types so I had to box int in an object.
=========
EDIT 1 (old, just leaving there as reference to make sense of the comments below):
you could have both a non-generic marker interface for when you need to act on the container (but don't care about the "wrapped" type) and a covariant generic one for when you need the type information.
Something like:
interface IFoo {}
interface IFoo<out T> : IFoo {
T Value {get;}
}
class Foo<T> : IFoo<T> {
readonly T _value;
public Foo(T value) {this._value=value;}
public T Value {get {return _value;}}
}
Suppose you have this simple hierarchy of classes:
public class Person
{
public virtual string Name {get {return "anonymous";}}
}
public class Paolo : Person
{
public override string Name {get {return "Paolo";}}
}
you could have functions that work either on any IFoo (when you don't care if Foo wraps a Person) or specifically on IFoo<Person> (when you do care):
e.g.
static class Functions
{
// this is where you would do DoSomethingWithContainer(IFoo<?> foo)
// with hypothetical java-like wildcards
public static void DoSomethingWithContainer(IFoo foo)
{
Console.WriteLine(foo.GetType().ToString());
}
public static void DoSomethingWithGenericContainer<T>(IFoo<T> el)
{
Console.WriteLine(el.Value.GetType().ToString());
}
public static void DoSomethingWithContent(IFoo<Person> el)
{
Console.WriteLine(el.Value.Name);
}
}
which you could use like this:
    // note that IFoo can be covariant, but Foo can't,
    // so we need a List<IFoo
var lst = new List<IFoo<Person>>
{
new Foo<Person>(new Person()),
new Foo<Paolo>(new Paolo())
};
foreach(var p in lst) Functions.DoSomethingWithContainer(p);
foreach(var p in lst) Functions.DoSomethingWithGenericContainer<Person>(p);
foreach(var p in lst) Functions.DoSomethingWithContent(p);
// OUTPUT (LinqPad)
// UserQuery+Foo`1[UserQuery+Person]
// UserQuery+Foo`1[UserQuery+Paolo]
// UserQuery+Person
// UserQuery+Paolo
// anonymous
// Paolo
One notable thing in the output is that even the function that only received IFoo still had and printed the full type information which in java would have been lost with type erasure.
It seems that in C#, you have to create a list of Foo, which you use as base type of Foo<T>. However, you can't easily get back to Foo<T> from there.
One solution I found is to add an abstract method to Foo for each function SomeFn<T>(Foo<T>), and implement them in Foo<T> by calling SomeFn(this). However, that would mean that every time you want to define a new (external) function on Foo<T>, you have to add a forwarding function to Foo, even though it really shouldn't have to know about that function:
abstract class Foo {
public abstract void DoSomething();
}
class Foo<T> : Foo {
public override void DoSomething() {
Functions.DoSomething(this);
}
// ...
}
static class Functions {
public static void DoSomething<T>(Foo<T> foo) {
// ...
}
public static void DoSomething(List<Foo> list) {
foreach(Foo item in list)
item.DoSomething();
}
}
A slightly cleaner solution from a design perspective seems to be a Visitor pattern which generalizes the above approach to a degree and severs the coupling between Foo and the specific generic functions, but that makes the whole thing even more verbose and complicated.
interface IFooVisitor {
void Visit<T>(Foo<T> foo);
}
class DoSomethingFooVisitor : IFooVisitor {
public void Visit<T>(Foo<T> foo) {
// ...
}
}
abstract class Foo {
public abstract void Accept(IFooVisitor foo);
}
class Foo<T> : Foo {
public override void Accept(IFooVisitor foo) {
foo.Visit(this);
}
// ...
}
static class Functions {
public static void DoSomething(List<Foo> list) {
IFooVisitor visitor = new DoSomethingFooVisitor();
foreach (Foo item in list)
item.Accept(visitor);
}
}
This would almost be a good solution IMO, if it was easier to create a Visitor. Since C# apparently does not allow generic delegates/lambdas, you cannot specify the visitor inline and take advantage of closures though - As far as I can tell, each Visitor needs to be a new explicitly defined class with possible extra parameters as fields. The Foo type also has to explicitly support this scheme by implementing the Visitor pattern.
For those who may still find this interesting, here is the best solution I could come up with that also meets the "bonus requirement" of not touching the original type in any way. It is basically a Visitor pattern with the twist that we don't store the Foo<T> directly in our container, but rather store a delegate which calls an IFooVisitor on our Foo<T>. Notice how we can easily make a list of those because T is not actually part of the delegates' type.
// The original type, unmodified
class Pair<T> {
public T First, Second;
}
// Interface for any Action on a Pair<T>
interface IPairVisitor {
void Visit<T>(Pair<T> pair);
}
class PairSwapVisitor : IPairVisitor {
public void Visit<T>(Pair<T> pair) {
Application.Swap(pair);
}
}
class PairPrintVisitor : IPairVisitor {
public void Visit<T>(Pair<T> pair) {
Console.WriteLine("Pair<{0}>: ({1},{2})", typeof(T), pair.First, pair.Second);
}
}
// General interface for a container that follows the Visitor pattern
interface IVisitableContainer<T> {
void Accept(T visitor);
}
// The implementation of our Pair-Container
class VisitablePairList : IVisitableContainer<IPairVisitor> {
private List<Action<IPairVisitor>> m_visitables = new List<Action<IPairVisitor>>();
public void Add<T>(Pair<T> pair) {
m_visitables.Add(visitor => visitor.Visit(pair));
}
public void Accept(IPairVisitor visitor) {
foreach (Action<IPairVisitor> visitable in m_visitables)
visitable(visitor);
}
}
static class Application {
public static void Swap<T>(Pair<T> pair) {
T temp = pair.First;
pair.First = pair.Second;
pair.Second = temp;
}
static void Main() {
VisitablePairList list = new VisitablePairList();
list.Add(new Pair<int> { First = 1, Second = 2 });
list.Add(new Pair<string> { First = "first", Second = "second" });
list.Accept(new PairSwapVisitor());
list.Accept(new PairPrintVisitor());
Console.ReadLine();
}
}
Output:
Pair<System.Int32>: (2,1)
Pair<System.String>: (second,first)

Overloaded Method..why is base class given precedence?

In the following code, i have an overloaded method, one that takes a parameter of type ClazzA and the other of type ClazzB. In the code shown, the first GetDescription method (the one that takes ClazzA as a parameter) is called. I think i understand why.
My question is..is there an elegant way of having the method that takes clazzB called first if the underlying object is of type classB (without having to inspect each object and casting it to clazzB)?
public class ClazzA
{
public virtual string Descr { get { return "A"; } }
}
public class ClazzB : ClazzA
{
public override string Descr { get { return "B"; } }
}
public static class test
{
public static void Main()
{
ClazzA test = new ClazzB();
GetDecription(test);
}
public static void GetDecription(ClazzA someClazz)
{
Debug.WriteLine("I am here");
}
public static void GetDecription(ClazzB someClazz)
{
Debug.WriteLine("I want to be here");
}
}
Output: "I am here"
I really want the 2nd method to be called since 'test' is of type ClassB. Curerently the only two solutions i have is:
if (test is ClazzB)
return GetDescription( (ClazzB) test );
or
In ClassA do pretty much the same thing...check the type and delegate to the 2nd method
Both of these require inspection of the object to determine its type
Overloads are determined at compile time. The compile time type of the reference is ClazzA so that overload is chosen. What you are asking for is related to multiple dispatch. C# and many other languages like C++ and Java only support single dispatch (via virtual methods). There are a number of ways people have come up with to work around this. The purest OO way of doing this is the visitor pattern. You modify the classes to contain a method (Accept) which then passes the this reference to a method on the visitor (Visit). This works because you override the Accept method in each subclass so that this will be the object's actual type. All the visitor needs is a specific method for each subclass that you want to support (see wikipedia for more details).
A sample:
public class ClazzA
{
public virtual string Accept(ClassVisitor visitor)
{
return visitor.Visit(this);
}
}
public class ClazzB : ClazzA
{
public override string Accept(ClassVisitor visitor)
{
return visitor.Visit(this);
}
}
public abstract class ClassVisitor
{
public abstract string Visit(ClazzA a);
public abstract string Visit(ClazzB b);
}
public class GetDescriptionVisitor : ClassVisitor
{
public override string Visit(ClazzA a)
{
return "A";
}
public override string Visit(ClazzB b)
{
return "B";
}
}
Usage:
ClassVisitor visitor = new GetDescriptionVisitor();
ClazzA b = new ClazzB();
Console.WriteLine(b.Accept(visitor)); // prints "B"
Because the method overload resolution occurs at compile-time. In terms of dealing with this situation, if you are using C# 4 then you could use dynamic so that the overload resolution is deferred to execution-time.
dynamic instance = new ClazzB();
Console.WriteLine(GetDescription(instance));
Alternatively, you could use a Visitor Pattern something like the following but this double-dispatch approach feels like a lot of work. Note the repetitive Visit method that must be re-implement in every derived type!
public interface IVisitable
{
string Visit(DescriptionVisitor visitor);
}
public class ClazzA : IVisitable
{
public virtual string Visit(DescriptionVisitor visitor)
{
return visitor.Visit(this);
}
}
public class ClazzB : ClazzA
{
public override string Visit(DescriptionVisitor visitor)
{
return visitor.Visit(this);
}
}
public class DescriptionVisitor
{
public string Visit(ClazzA item) { return "Description A"; }
public string Visit(ClazzB item) { return "Description B"; }
}
Then the following will ultimately still call the overload in DescriptionVisitor that takes ClazzB.
var visitor = new DescriptionVisitor();
ClazzA a = new ClazzB();
Console.WriteLine(a.Visit(visitor));
What you're trying to do is probably better performed using polymorphism, like so:
public interface IProvideDescription {
string GetDescription();
}
public class A : IProvideDescription {
public string GetDescription() {
return "I'm an A";
}
}
public class B : IProvideDescription {
public string GetDescription() {
return "I'm a B";
}
}
// to execute:
IProvideDescription x = new A();
Console.WriteLine(x.GetDescription());
x = new B();
Console.WriteLine(x.GetDescription());
To answer the question in your title ("...why is the base class given precedence?"), look at what your variable test is declared as (answer: your base class). When the overload is selected, all the method call knows is that you're passing a variable of type ClazzA into it. Sure, you've assigned it an object of type ClazzB, but suppose your assignment statement was more complex:
ClazzA test = GiveMeSomeObject();
The method selection has to occur at compile time to provide type safety.
You can get the behaviour you want by using the "dynamic" keyword which was introduced in .Net 4.0. It evaluates the type at runtime and will pick the right overload.
public static class test
{
public static void Main()
{
dynamic test = new ClazzB();
GetDecription(test);
}
public static void GetDecription(ClazzA someClazz)
{
Debug.WriteLine("I am here");
}
public static void GetDecription(ClazzB someClazz)
{
Debug.WriteLine("I want to be here");
}
}
Generally it's not a responsibility of external class to identify class type.
if you need a polymorphic behavior, just put GetDescription into ClassA as virtual function and then override in ClassB - that will be conceptually correct.
As #roken mentioned, your example will actually result in B since the Descr property is overridden. If this is all you're doing, remove the ClazzB overload and use the polymorphic behavior you've already got. If you actually need to do something different in the methods and overloading is the best way to do that, you could do it via dynamic overload resolution:
GetDecription((dynamic)test);
However, this has some drawbacks, such as performance and a lack of compile-time testing that GetDescription(test) makes sense. I'd recommend doing a runtime check within GetDecription(ClazzA):
if (someClazz is ClazzB)
{
GetDescription((ClazzB)someClazz);
return;
}
You can get by with just a single GetDescription() method:
public String GetDescription(ClassA in) {
if (in is ClassB) {
return (in as ClassB).Descr
}
return in.Descr;
}

How can I overload a C# method by specific instances of a generic type

Coming from a C++ background, I've run into a snag with overloading based on a specific instance of a generic type. The following doesn't work since only once instance of the code for the Foo<T> class is ever generated, so inside the Method, the type of this is simply Foo<T>, not Foo<A> or Foo<B> as I'd hoped. In C++ I'm used to templates being instantiated as unique types.
using System.Collections.Generic;
class A
{
// Concrete class
}
class B
{
// Concrete class
}
class Bar
{
public void OverloadedMethod(Foo<A> a) {} // do some A related stuff
public void OverloadedMethod(Foo<B> b) {} // do some B related stuff
public void OverloadedMethod(OtherFoo of) {} // do some other stuff
public void VisitFoo(FooBase fb) { fb.Method(this); }
}
abstract class FooBase
{
public abstract void Method(Bar b);
}
class Foo<T> : FooBase
{
// Class that deals with As and Bs in an identical fashion.
public override void Method(Bar b)
{
// Doesn't compile here
b.OverloadedMethod(this);
}
}
class OtherFoo : FooBase
{
public override void Method(Bar b)
{
b.OverloadedMethod(this);
}
}
class Program
{
static void Main(string[] args)
{
List<FooBase> ListOfFoos = new List<FooBase>();
ListOfFoos.Add(new OtherFoo());
ListOfFoos.Add(new Foo<A>());
ListOfFoos.Add(new Foo<B>());
Bar b = new Bar();
foreach (FooBase fb in ListOfFoos)
b.VisitFoo(fb);
// Hopefully call each of the Bar::Overloaded methods
}
}
Is there a way to get something like this to work in C#? I'd rather not have to duplicate the code in Foo as separate classes for every type I want to use it for.
Edit:
Hopefully this is a little clearer.
I now have a genuinely complete piece of code which demonstrates the problem. Note to OP: please try compiling your code before posting it. There were a bunch of things I had to do to get this far. It's good to make it as easy as possible for other people to help you. I've also removed a bunch of extraneous bits. OtherFoo isn't really relevant here, nor is FooBase.
class A {}
class B {}
class Bar
{
public static void OverloadedMethod(Foo<A> a) { }
public static void OverloadedMethod(Foo<B> b) { }
}
class Foo<T>
{
// Class that deals with As and Bs in an identical fashion.
public void Method()
{
// Doesn't compile here
Bar.OverloadedMethod(this);
}
}
Yes, this doesn't compile. What did you expect it to do, exactly? Bear in mind that the overload resolution is performed at compile time, not execution time. As fallen888 says, you could cast and call the appropriate overloaded method - but which of the two overloads would you expect the compiler to pick otherwise? What do you want it to do with Foo<string> instead of Foo<A> or Foo<B>?
This all goes to demonstrate that .NET generics are indeed significantly different from C++ templates, of course...
I haven't tried it but it seems you should be able to achieve what you want by making A & B visitable (e.g. with the acyclic visitor pattern).
This works for the static case. Dealing with instance functions would be a bit more complicated. This post from Jon Skeet might provide a reasonable way to deal with instance methods.
class Program
{
static void Main(string[] args)
{
var testA = new Foo<A>();
testA.Method();
var testB = new Foo<B>();
testB.Method();
Console.ReadLine();
var testString = new Foo<string>(); //Fails
testString.Method();
Console.ReadLine();
}
}
class A { }
class B { }
class Bar
{
public static void OverloadedMethod(Foo<A> a)
{
Console.WriteLine("A");
}
public static void OverloadedMethod(Foo<B> b)
{
Console.WriteLine("B");
}
}
class Foo<T>
{
static Foo()
{
overloaded = (Action<Foo<T>>)Delegate.CreateDelegate(typeof(Action<Foo<T>>), typeof(Bar).GetMethod("OverloadedMethod", new Type[] { typeof(Foo<T>) }));
}
public void Method()
{
overloaded(this);
}
private static readonly Action<Foo<T>> overloaded;
}
Edit: I'm not sure that you can complete this as you're attempting. I've tried all sorts of tricks to attempt to get this to work and can't get it to compile. The best I can do is to pull the method call outside of my Generic class. If your method call is outside, then you can specifically define what T is in the generic. However, inside the method, at compile time, the compiler doesn't know what T will be so it doesn't know which overloaded method to call. The only way I can see around this is to use a switch to determine the type of T and manually specify the overload to call.
The best I can do is this, which isn't quite what you're after, but it could be used to a similar effect:
class Stuff<T>
{
public T value { get; set; }
}
class Program
{
static void DummyFunc(Stuff<int> inst)
{
Console.WriteLine("Stuff<int>: {0}", inst.value.ToString());
}
static void DummyFunc(Stuff<string> inst)
{
Console.WriteLine("Stuff<string>: {0}", inst.value);
}
static void DummyFunc(int value)
{
Console.WriteLine("int: {0}", value.ToString());
}
static void DummyFunc(string value)
{
Console.WriteLine("string: {0}", value);
}
static void Main(string[] args)
{
var a = new Stuff<string>();
a.value = "HelloWorld";
var b = new Stuff<int>();
b.value = 1;
var c = "HelloWorld";
var d = 1;
DummyFunc(a);
DummyFunc(b);
DummyFunc(c);
DummyFunc(d);
}
}
and got output:
Stuff<string>: HelloWorld
Stuff<int>: 1
string: HelloWorld
int: 1
I've got four overloaded functions referencing two referencing generic classes (one for int and one for string) and two referencing regular types (one for int and one for string) and it all works okay... is this what you're after?
Edit: The problem doesn't seem to be with the calling of the overloaded methods, it has to do with your foreach which is trying to convert all items in the list to the same type as the first in order to reference the overloaded method. The first item that doesn't conform to that exact definition will cause your compile to fail.
I was hoping to find an easier way to do this but for now I'm going with this:
Replace Foo<T> class with these classes:
abstract class Foo<T> : FooBase
{
// Class that deals with As and Bs in an identical fashion.
}
class Foo_A : Foo<A>
{
public override void Method(Bar b)
{
b.OverloadedMethod(this);
}
}
class Foo_B : Foo<B>
{
public override void Method(Bar b)
{
// Doesn't compile here
b.OverloadedMethod(this);
}
}
And change the instantiations to
List<FooBase> ListOfFoos = new List<FooBase>();
ListOfFoos.Add(new OtherFoo());
ListOfFoos.Add(new Foo_A());
ListOfFoos.Add(new Foo_B());
This at least doesn't require dublicating the code in Foo<T>, and just requires me to forward the constructors.

Categories