Pluggable framework
Imagine a simple pluggable system, which is pretty straightforward using inheritance polymorphism:
We have a graphics rendering system
There are different types of graphics shapes (monochrome, color, etc.) that need rendering
Rendering is done by a data-specific plugin, e.g. a ColorRenderer will render a ColorShape.
Every plugin implements IRenderer, so they can all be stored in an IRenderer[].
On startup, IRenderer[] is populated with a series of specific renderers
When data for a new shape is received, a plugin is chosen from the array based on the type of the shape.
The plugin is then invoked by calling its Render method, passing the shape as its base type.
The Render method is overridden in each descendant class; it casts the Shape back to its descendant type and then renders it.
Hopefully the above is clear-- I think it is a pretty common sort of setup. Very easy with inheritance polymorphism and run-time casting.
Doing it without casting
Now the tricky part. In response to this question, I wanted to come up with a way to do this all without any casting whatsoever. This is tricky because of that IRenderer[] array-- to get a plugin out of the array, you would normally need to cast it to a specific type in order to use its type-specific methods, and we can't do that. Now, we could get around that by interacting with a plugin only with its base class members, but part of the requirements was that the renderer must run a type-specific method that has a type-specific data packet as an argument, and the base class would not be able to do that because there is no way to pass it a type-specific data packet without a casting it to the base and then back to the ancestor. Tricky.
At first I thought it was impossible, but after a few tries I found I could make it happen by juking the c# generic system. I create an interface that is contravariant with respect to both plugin and shape type and then used that. Resolution of the renderer is decided by the type-specific Shape. Xyzzy, the contravariant interface makes the cast unnecessary.
Here is the shortest version of the code I could come up with as an example. This compiles and runs and behaves correctly:
public enum ColorDepthEnum { Color = 1, Monochrome = 2 }
public interface IRenderBinding<in TRenderer, in TData> where TRenderer : Renderer
where TData: Shape
{
void Render(TData data);
}
abstract public class Shape
{
abstract public ColorDepthEnum ColorDepth { get; }
abstract public void Apply(DisplayController controller);
}
public class ColorShape : Shape
{
public string TypeSpecificString = "[ColorShape]"; //Non-virtual, just to prove a point
override public ColorDepthEnum ColorDepth { get { return ColorDepthEnum.Color; } }
public override void Apply(DisplayController controller)
{
IRenderBinding<ColorRenderer, ColorShape> renderer = controller.ResolveRenderer<ColorRenderer, ColorShape>(this.ColorDepth);
renderer.Render(this);
}
}
public class MonochromeShape : Shape
{
public string TypeSpecificString = "[MonochromeShape]"; //Non-virtual, just to prove a point
override public ColorDepthEnum ColorDepth { get { return ColorDepthEnum.Monochrome; } }
public override void Apply(DisplayController controller)
{
IRenderBinding<MonochromeRenderer, MonochromeShape> component = controller.ResolveRenderer<MonochromeRenderer, MonochromeShape>(this.ColorDepth);
component.Render(this);
}
}
abstract public class Renderer : IRenderBinding<Renderer, Shape>
{
public void Render(Shape data)
{
Console.WriteLine("Renderer::Render(Shape) called.");
}
}
public class ColorRenderer : Renderer, IRenderBinding<ColorRenderer, ColorShape>
{
public void Render(ColorShape data)
{
Console.WriteLine("ColorRenderer is now rendering a " + data.TypeSpecificString);
}
}
public class MonochromeRenderer : Renderer, IRenderBinding<MonochromeRenderer, MonochromeShape>
{
public void Render(MonochromeShape data)
{
Console.WriteLine("MonochromeRenderer is now rendering a " + data.TypeSpecificString);
}
}
public class DisplayController
{
private Renderer[] _renderers = new Renderer[10];
public DisplayController()
{
_renderers[(int)ColorDepthEnum.Color] = new ColorRenderer();
_renderers[(int)ColorDepthEnum.Monochrome] = new MonochromeRenderer();
//Add more renderer plugins here as needed
}
public IRenderBinding<T1,T2> ResolveRenderer<T1,T2>(ColorDepthEnum colorDepth) where T1 : Renderer where T2: Shape
{
IRenderBinding<T1, T2> result = _renderers[(int)colorDepth];
return result;
}
public void OnDataReceived<T>(T data) where T : Shape
{
data.Apply(this);
}
}
static public class Tests
{
static public void Test1()
{
var _displayController = new DisplayController();
var data1 = new ColorShape();
_displayController.OnDataReceived<ColorShape>(data1);
var data2 = new MonochromeShape();
_displayController.OnDataReceived<MonochromeShape>(data2);
}
}
If you run Tests.Test1() the output will be:
ColorRenderer is now rendering a [ColorShape]
MonochromeRenderer is now rendering a [MonochromeShape]
Beautiful, it works, right? Then I got to wondering... what if ResolveRenderer returned the wrong type?
Type safe?
According to this MSDN article,
Contravariance, on the other hand, seems counterintuitive....This seems backward, but it is type-safe code that compiles and runs. The code is type-safe because T specifies a parameter type.
I am thinking, there is no way this is actually type safe.
Introducing a bug that returns the wrong type
So I introduced a bug into the controller so that is mistakenly stores a ColorRenderer where the MonochromeRenderer belongs, like this:
public DisplayController()
{
_renderers[(int)ColorDepthEnum.Color] = new ColorRenderer();
_renderers[(int)ColorDepthEnum.Monochrome] = new ColorRenderer(); //Oops!!!
}
I thought for sure I'd get some sort of type mismatch exception. But no, the program completes, with this mysterious output:
ColorRenderer is now rendering a [ColorShape]
Renderer::Render(Shape) called.
What the...?
My questions:
First,
Why did MonochromeShape::Apply call Renderer::Render(Shape)? It is attempting to call Render(MonochromeShape), which obviously has a different method signature.
The code within the MonochromeShape::Apply method only has a reference to an interface, specifically IRelated<MonochromeRenderer,MonochromeShape>, which only exposes Render(MonochromeShape).
Although Render(Shape) looks similar, it is a different method with a different entry point, and isn't even in the interface being used.
Second,
Since none of the Render methods are virtual (each descendant type introduces a new, non-virtual, non-overridden method with a different, type-specific argument), I would have thought that the entry point was bound at compile time. Are method prototypes within a method group actually chosen at run-time? How could this possibly work without a VMT entry for dispatch? Does it use some sort of reflection?
Third,
Is c# contravariance definitely not type safe? Instead of an invalid cast exception (which at least tells me there is a problem), I get an unexpected behavior. Is there any way to detect problems like this at compile time, or at least to get them to throw an exception instead of doing something unexpected?
OK, first of all, do not write generic types like this. As you have discovered, it rapidly becomes a huge mess. Never do this:
class Animal {}
class Turtle : Animal {}
class BunchOfAnimals : IEnumerable<Animal> {}
class BunchOfTurtles : BunchOfAnimals, IEnumerable<Turtle> {}
OH THE PAIN. Now we have two paths by which to get an IEnumerable<Animal> from a BunchOfTurtles: Either ask the base class for its implementation, or ask the derived class for its implementation of the IEnumerable<Turtle> and then covariantly convert it to IEnumerable<Animal>. The consequences are: you can ask a bunch of turtles for a sequence of animals, and giraffes can come out. That's not a contradiction; all the capabilities of the base class are present in the derived class, and that includes generating a sequence of giraffes when asked.
Let me re-emphasize this point so that it is very clear. This pattern can create in some cases implementation-defined situations where it becomes impossible to determine statically what method will actually be called. In some odd corner cases, you can actually have the order in which the methods appear in the source code be the deciding factor at runtime. Just don't go there.
For more on this fascinating topic I encourage you to read all the comments to my 2007 blog post on the subject: https://blogs.msdn.microsoft.com/ericlippert/2007/11/09/covariance-and-contravariance-in-c-part-ten-dealing-with-ambiguity/
Now, in your specific case everything is nicely well defined, it's just not defined as you think it ought to be.
To start with: why is this typesafe?
IRenderBinding<MonochromeRenderer, MonochromeShape> component = new ColorRenderer();
Because you said it should be. Work it out from the point of view of the compiler.
A ColorRenderer is a Renderer
A Renderer is a IRenderBinding<Renderer, Shape>
IRenderBinding is contravariant in both its parameters, so it may always be made to have a more specific type argument.
Therefore a Renderer is an IRenderBinding<MonochromeRenderer, MonochromeShape>
Therefore the conversion is valid.
Done.
So why is Renderer::Render(Shape) called here?
component.Render(this);
You ask:
Since none of the Render methods are virtual (each descendant type introduces a new, non-virtual, non-overridden method with a different, type-specific argument), I would have thought that the entry point was bound at compile time. Are method prototypes within a method group actually chosen at run-time? How could this possibly work without a VMT entry for dispatch? Does it use some sort of reflection?
Let's go through it.
component is of compile-time type IRenderBinding<MonochromeRenderer, MonochromeShape>.
this is of compile-time type MonochromeShape.
So we are calling whatever method implements IRenderBinding<MonochromeRenderer, MonochromeShape>.Render(MonochromeShape) on a ColorRenderer.
The runtime must figure out which interface is actually meant. ColorRenderer implements IRenderBinding<ColorRenderer, ColorShape> directly and IRenderBinding<Renderer, Shape> via its base class. The former is not compatible with IRenderBinding<MonochromeRenderer, MonochromeShape>, but the latter is.
So the runtime deduces that you meant the latter, and executes the call as though it were IRenderBinding<Renderer, Shape>.Render(Shape).
So which method does that call? Your class implements IRenderBinding<Renderer, Shape>.Render(Shape) on the base class so that's the one that's called.
Remember, interfaces define "slots", one per method. When the object is created, each interface slot is filled with a method. The slot for IRenderBinding<Renderer, Shape>.Render(Shape) is filled with the base class version, and the slot for IRenderBinding<ColorRenderer, ColorShape>.Render(ColorShape) is filled with the derived class version. You chose the slot from the former, so you get the contents of that slot.
Is c# contravariance definitely not type safe?
I promise you it is type safe. As you should have noticed: every conversion you made without a cast was legal, and every method you called was called with something of a type that it expected. You never invoked a method of ColorShape with a this referring to a MonochromeShape, for instance.
Instead of an invalid cast exception (which at least tells me there is a problem), I get an unexpected behavior.
No, you get entirely expected behaviour. You just have created a type lattice that is extraordinarily confusing, and you don't have a sufficient level of understanding of the type system to understand the code you wrote. Don't do that.
Is there any way to detect problems like this at compile time, or at least to get them to throw an exception instead of doing something unexpected?
Don't write code like that in the first place. Never implement two versions of the same interface such that they may unify via covariant or contravariant conversions. It is nothing but pain and confusion. And similarly, never implement an interface with methods that unify under generic substitution. (For example, interface IFoo<T> { void M(int); void M(T); } class Foo : IFoo<int> { uh oh } )
I considered adding a warning to that effect, but it was difficult to see how to turn off the warning in the rare cases where it is desirable. Warnings that can only be turned off with pragmas are poor warnings.
First. MonochromeShape::Apply call Renderer::Render(Shape) because of the following:
IRenderBinding<ColorRenderer, ColorShape> x1 = new ColorRenderer();
IRenderBinding<Renderer, Shape> x2 = new ColorRenderer();
// fails - cannot convert IRenderBinding<ColorRenderer, ColorShape> to IRenderBinding<MonochromeRenderer, MonochromeShape>
IRenderBinding<MonochromeRenderer, MonochromeShape> c1 = x1;
// works, because you can convert IRenderBinding<Renderer, Shape> toIRenderBinding<MonochromeRenderer, MonochromeShape>
IRenderBinding<MonochromeRenderer, MonochromeShape> c2 = x2;
So in short: ColorRenderer inherits from Renderer and that in turn implements IRenderBinding<Renderer, Shape>. This interface is what allows ColorRendered to be implicitly converted to IRenderBinding<MonochromeRenderer, MonochromeShape>. This interface is implemented by class Renderer and so it's not suprising that Renderer.Render is called when you call MonochromeShape::Apply. The fact you pass instance of MonochromeShape and not Shape is not a problem exactly because TData is contravariant.
About your second question. Dispatch by interface is virtual just by definition. In fact, if method implements some method from interface - it's marked as virtual in IL. Consider this:
class Test : ITest {
public void DoStuff() {
}
}
public class Test2 {
public void DoStuff() {
}
}
interface ITest {
void DoStuff();
}
Method Test.DoStuff has following signature in IL (note virtual:
.method public final hidebysig virtual newslot instance void
DoStuff() cil managed
Method Test2.DoStuff is just:
.method public hidebysig instance void
DoStuff() cil managed
As for third question I think it's clear from above that it behaves as expected and is type-safe exactly because no invalid cast exceptions are possible.
Related
I've been searching for a while on this because I'm naturally forgetful and I thought it would be nice to build something (an abstract class, interface, etc.?) that would force me to implement certain bits of code in a class I was writing.
In particular, I would like to force a new class to always have a constructor that takes a single parameter typed as itself in order to make duplication of the object easier. I've seen articles/questions elsewhere that talk about this, but I'm not sure this particular question has been asked (at least that I can find) or I'm simply not understanding enough of the other articles/questions to realize it. My apologies in advance.
I'm not interested in having a constructor in an abstract class, interface, etc. actually do anything. I'm merely interested in defining the requirement for a constructor signature in a derived class.
My ideal class would look like this:
public class GoodClass
{
public GoodClass(GoodClass goodClass)
{
// copy components of goodClass to this instance
}
}
So, I first began researching interfaces and also started reading up on abstract classes. I was thinking something like the code below would work, but alas I get errors. Is what I'm trying to do even possible? Is there any other way I could accomplish my goal without putting a sticky note on my monitor? :)
abstract class SelfConstructor
{
abstract public SelfConstructor(SelfConstructor) { }
}
class NewClass : SelfConstructor
{
//Required by SelfConstructor:
public NewClass(NewClass newClass)
{
// copy components of newClass to this instance
}
}
You could write a ReSharper plugin that recognises this case and highlights the class if it doesn't have a "copy constructor". This would be a daemon stage that would process the file as it's being edited, and add highlights. You can look through the abstract syntax tree of the file, look for all instances of IConstructorDeclaration, and then get the constructor's parameters from the ParameterDeclarations property. You can check that there is a constructor that only has one parameter, and that parameter is the same type as the class it's declared in.
You can compare the types by getting the constructor's parameter's TypeUsage and trying to downcast to IUserTypeUsage. You can then use ScalarTypeName.Reference.Resolve() to get an instance of IDeclaredElement. Compare this against the class's IClassDeclaration.DeclaredElement to see if they're the same instance.
In C++, what you are talking about is a copy constructor, you actually get one by default!
C# doesn't have that concept (though of course you can define one); however, it is easier (and preferred) to simply implement ICloneable (MSDN), which requires you to implement the Clone method, that does the same thing.
Instead of:
object myObj = new CloneableObject(otherObj);
You write:
object myObj = otherObj.Clone();
The other thing you could do is force a constructor signature by not having a default:
public class BaseClass
{
//No abstract constructors!
public BaseClass(BaseClass copy)
{
}
}
Now when you derive, you have to use that overload in the constructor. Nothing will force the derived signature, but at least you have to explicitly use it:
public class DerivedClass : BaseClass
{
public DerivedClass() : base(this)
{
}
}
The above example clearly shows that it doesn't "force" you to have a copy constructor, but like a sticky note, would serve as a good reminder.
I would definitely go the interface route, as that is what is there for (and you can use an abstract implementation!).
Note that you can take advantage of Object.MemberwiseClone if you want a shallow copy for free. All objects get this, no interface required.
When I run code analysis (VS2013) with the 'Microsoft Managed Recommend Rules' rule set, the only warnings I get for my class library are of type CA1033: 'Interface methods should be callable by child types'. But I don't understand the rule in this situation:
/// An object that has a chemical formula
public interface IChemicalFormula
{
/// The chemical formula of the object
ChemicalFormula ChemicalFormula {get;}
}
public class ChemicalFormula: IChemicalFormula
{
ChemicalFormula IChemicalFormula.ChemicalFormula
{
get { return this; }
}
}
The docs recommends making a protected method with the same name so that deriving types can access it, but you cannot name a method the same as the enclosing type. They also recommend making the class sealed, but I don't want it to be sealed in this case. Is this a time just to ignore this rule, or is there an appropriate way to handle it?
EDIT
To add clarification why the class/interface is designed this way, I have another class, Peptide that contains a IChemicalFormula[] array to store modifications. Not every modification necessarily derives directly from ChemicalFormula, but they need to implement the IChemicalFormula interface. Therefore, if I modify an instance of a peptide withsome molecule (H2O for example), then ChemicalFormula class needs to also implement IChemicalFormula.
This is the description of the rule:
Consider a base type that explicitly implements a public interface
method. A type that derives from the base type can access the
inherited interface method only through a reference to the current
instance (this in C#) that is cast to the interface. If the derived
type re-implements (explicitly) the inherited interface method, the
base implementation can no longer be accessed. The call through the
current instance reference will invoke the derived implementation;
this causes recursion and an eventual stack overflow.
I think you should consider evaluating the usage of this property. A good example where TDD could be used to figure out the interface. There are some possible usages (and some invalid ones) below. I am not yet sure what you intend to achieve by looking at those.
In your example, let's say another class, NewChemicalForumla is derived from ChemicalForumula, and references ChemicalFormula, what does that mean?
public class NewChemicalFormula: ChemicalFormula
{
public void Method()
{
Console.WriteLine("{0}", ChemicalFormula.GetType()); // Compile error
Console.WriteLine("{0}", this.ChemicalFormula.GetType()); // Effectively same as above, compile error
Console.WriteLine("{0}", ((IChemicalFormula)this).ChemicalFormula.GetType()); // Works, is that what you intend?
}
}
Now from outside the class, there are two possibilities:
When you have a handle to a derived class:
new NewChemicalFormula().ChemicalFormula.GetType() // Error
or
// This works, is that what you intend to achieve?
((IChemicalFormula)new NewChemicalFormula()).ChemicalFormula.GetType()
When you have a handle to the IChemicalFormula already. In this case, ChemicalFormula seems redundant:
IChemicalFormula formula = new NewChemicalFormula();
Console.WriteLine("{0}", formula.GetType()); // Works, returns NewChemicalFormula
Console.WriteLine("{0}", formula.ChemicalFormula.GetType()); // Works, returns NewChemicalFormula
Console.WriteLine("{0}", formula.ChemicalFormula.Method()); // Compile error
formula.ChemicalFormula.Method() leads to an error because you must cast it to NewChemicalFormula before you can use Method(). Just because the property returns this doesn't help solve this problem.
So the FXCop warning is worth considering, and evaluating the design.
In a program I'm using the dynamic keyword to invoke the best matching method. However, I have found that the framework crashes with a StackOverflowException under some circumstances.
I have tried to simplify my code as much as possible while still being able to re-produce this problem.
class Program
{
static void Main(string[] args)
{
var obj = new SetTree<int>();
var dyn = (dynamic)obj;
Program.Print(dyn); // throws StackOverflowException!!
// Note: this works just fine for 'everything else' but my SetTree<T>
}
static void Print(object obj)
{
Console.WriteLine("object");
}
static void Print<TKey>(ISortedSet<TKey> obj)
{
Console.WriteLine("set");
}
}
That program would normally print "set" if the newed up instance implements the ISortedSet<TKey> interface and print "object" for anything else. But, with the following declarations a StackOverflowException is thrown instead (as noted in a comment above).
interface ISortedSet<TKey> { }
sealed class SetTree<TKey> : BalancedTree<SetTreeNode<TKey>>, ISortedSet<TKey> {}
abstract class BalancedTree<TNode>
where TNode : TreeNode<TNode> { }
abstract class SetTreeNode<TKey> : KeyTreeNode<SetTreeNode<TKey>, TKey> { }
abstract class KeyTreeNode<TNode, TKey> : TreeNode<TNode>
where TNode : KeyTreeNode<TNode, TKey> { }
abstract class TreeNode<TNode>
where TNode : TreeNode<TNode> { }
Whether this is a bug or not it is very troubling that a StackOverflowException is thrown as we are unable to catch it and also pretty much unable to determine in advance whether an exception will be thrown (and thereby terminate the process!).
Can someone please explain what's going on? Is this a bug in the framework?
When debugging and switching to "Disassembly mode" I'm seeing this:
Register dump at that location:
EAX = 02B811B4 EBX = 0641EA5C ECX = 02C3B0EC EDX = 02C3A504 ESI = 02C2564C
EDI = 0641E9AC EIP = 011027B9 ESP = 0641E91C EBP = 0641E9B8 EFL = 00000202
That doesn't tell me much more than being an indicator that this indeed must be some kind of bug in the framework.
I've filed a bug report on Microsoft Connect but I'm interested in knowing what's going on here. Are my class declarations unsupported in some way?
Not knowing WHY this is happening causes me to worry about other places where we are using the dynamic keyword. Can I not trust that at all?
I created a shorter, more to-the-point SSCCE that illustrates the problem:
class Program
{
static void Main()
{
dynamic obj = new Third<int>();
Print(obj); // causes stack overflow
}
static void Print(object obj) { }
}
class First<T> where T : First<T> { }
class Second<T> : First<T> where T : First<T> { }
class Third<T> : Second<Third<T>> { }
Looking at the call stack, it seems to be bouncing between two pairs of symbols in the C# runtime binder:
Microsoft.CSharp.RuntimeBinder.SymbolTable.LoadSymbolsFromType(
System.Type originalType
)
Microsoft.CSharp.RuntimeBinder.SymbolTable.GetConstructedType(
System.Type type,
Microsoft.CSharp.RuntimeBinder.Semantics.AggregateSymbol agg
)
and
Microsoft.CSharp.RuntimeBinder.Semantics.TypeManager.SubstTypeCore(
Microsoft.CSharp.RuntimeBinder.Semantics.CType type,
Microsoft.CSharp.RuntimeBinder.Semantics.SubstContext pctx
)
Microsoft.CSharp.RuntimeBinder.Semantics.TypeManager.SubstTypeArray(
Microsoft.CSharp.RuntimeBinder.Semantics.TypeArray taSrc,
Microsoft.CSharp.RuntimeBinder.Semantics.SubstContext pctx
)
If I had to hazard a guess, some of the generic type constraint nesting you've got going on has managed to confuse the binder into recursively walking the types involved in the constraints along with the constraints themselves.
Go ahead and file a bug on Connect; if the compiler doesn't get caught by this, the runtime binder probably shouldn't either.
This code example runs correctly:
class Program
{
static void Main()
{
dynamic obj = new Second<int>();
Print(obj);
}
static void Print(object obj) { }
}
internal class First<T>
where T : First<T> { }
internal class Second<T> : First<Second<T>> { }
This leads me to believe (without much knowledge of the internals of the runtime binder) that it's proactively checking for recursive constraints, but only one level deep. With an intermediary class in between, the binder ends up not detecting the recursion and tries to walk it instead. (But that's all just an educated guess. I'd add it to your Connect bug as additional information and see if it helps.)
The problem is that you are deriving a type from itself:
abstract class SetTreeNode<TKey> : KeyTreeNode<SetTreeNode<TKey>, TKey> { }
The type SetTreeNote<TKey> becomes KeyTreeNode<SetTreeNode<TKey>,TKey> which becomes KeyTreeNode<KeyTreeNode<SetTreeNode<TKey>,TKey>,TKey> and this goes on and on until the stack overflows.
I don't know what you are trying to accomplish by using this complex model, but that is your problem.
I managed to reduce it to this example which fails:
interface ISortedSet<TKey> { }
sealed class SetTree<TKey> : BalancedTree<SetTreeNode<TKey>>, ISortedSet<TKey> { }
abstract class BalancedTree<TNode> { }
abstract class SetTreeNode<TKey> : KeyTreeNode<SetTreeNode<TKey>, TKey> { }
abstract class KeyTreeNode<TNode, TKey> : TreeNode<TNode> { }
abstract class TreeNode<TNode> { }
And then I fixed it by doing this:
interface ISortedSet<TKey> { }
sealed class SetTree<TKey> : BalancedTree<SetTreeNode<TKey>>, ISortedSet<TKey> { }
abstract class BalancedTree<TNode> { }
abstract class SetTreeNode<TKey> : KeyTreeNode<TKey, TKey> { }
abstract class KeyTreeNode<TNode, TKey> : TreeNode<TNode> { }
abstract class TreeNode<TNode> { }
The only difference between the two is that I replaced KeyTreeNode<SetTreeNode<TKey>, TKey> with KeyTreeNode<TKey, TKey>
Can someone please explain what's going on? Is this a bug in the framework?
Yes.
The issue is in the way that generic types are resolved into their particular concrete uses.
Okay, let's start with some obvious stuff so as to build up to what the compiler is getting wrong. As you know, with something like List<int> the compilers (whether it's the dynamic compiler, or any of the static compilers since C#2 introduced generics) have to take the List<> type and the int type and combine information about both of those to produce the List<int> type.
Now, consider:
public class Base<T, U>
{
}
public class Derived<T> : Base<T, int>
{
}
Derived<long> l = new Derived<long>();
Here you can see that in the same work on the types Derived<T> and long the compiler has to fill three slots:
The T defined on Derived<>, which gets filled with long.
The T defined on Base<,> which gets filled with the T defined on Derived<>, which was filled with long.
The U defined on Base<,> which gets filled with int.
When you consider nested classes, long inheritance chains, generic types derived from other generic types and adding further generic parameters, and so on, you can see that there's a good few different permutations to cover. If you're starting with Derived<long> and have to answer the question "what is the base type of the class?" (which obviously compilers need to consider a lot) then all of this has to be worked out.
The dynamic compiler was based on the pre-Roslyn static compiler, which was based on the compiler before that which was actually written in C++ rather than C# (there is still quite a lot of the dynamic compiler that while it's in C#, smells of C++). The can be considered as being more similar in end point (code that can be executed) than in start point; a bunch of text that has to be parsed for the static compiler to understand what types and operations are involved vs the dynamic compiler starting with already-existing types and operations represented by objects and flags.
One thing they both need to know that is that if a type is mentioned several times, that it's the same type (that's pretty much the most basic definition of what a type means, after all). If we compile new List<int>((int)x) that would obviously not work unless it knew int meant the same thing both times. They also need to avoid chewing up gigs of RAM.
Both problems are solved by a hash-consing or flyweight-like approach. When it goes to construct the object representing a particular type, it first sees if it has already constructed that type, and only constructs a new one if necessary. This also helps a lot of relationships within hierarchies be correctly constructed, though clearly not the particular case in your question.
For most types (all except for a few special cases like pointers, references, arrays, nullables [though there's an exception to that exception], type parameters… okay, there's actually quite a few exceptions) the state is mostly three things:
A symbol representing the type without specific type-parameters (which is the totality of the representation for non-generic types) but which does include type parameters of the generic definition (for Dictionary<int, int> it has the TKey and TValue of Dictionary<TKey, TValue>).
The set of the types that are parameters directly on the type (whether the T of List<T> for the open type, the int of List<int> for the constructed type, or a mix for e.g. Dictionary<T, int> relative to some generic type or method that defines T).
The set of the type parameters that are either directly on the type (as above) or on an outer type it is nested in.
Okay, so far, so good. If it needs to do something with List<int>.Enumerator it first either finds the List<T> symbol in the store, or adds it if new, then finds List<T>.Enumerator symbol in the store, or adds it if new, then finds int in the store (int is preloaded as a very common type) and finally finds the type that combines List<T>.Enumerator with int in the store, or adds it if new. We now have the only List<int>.Enumerator type object.
The problem, which caused your bug, comes in at the end of this last step. Consider what we said above about having to assign types to base types when creating a concrete implementation of a type. The base type of a concrete generic type is a concrete type, potentially itself a concrete generic type, but the information we have here is of the generic type and some type arguments: We do not know what the concrete generic type is.
The method for finding the base type is lazy-loaded, but calls into the symbol that doesn't know the type parameters to use.
The solution used was to temporarily define that symbol's base type in terms of the concrete base type, call the lazy-loading base-type method, and then set it back again.
I don't know why something was lazy-loaded when it was called immediately after creation. At a guess, I'd say it was something that made more sense in terms of the static compilation, and so got ported over that way rather than rewrite the mechanism from scratch (which would be a more risky approach in most regards).
This works pretty well, even with quite complicated hierarchies. However, if there's a hierarchy that is both circular in terms of type parameters and has more than one step before a non-generic type (such as object) is reached (so the fix-up has to recurse on a base type too) then it isn't able to find the type it's in the process of making (remember the bit about storing the objects for types) because it's been temporarily changed to make the fix-up work, and has to make it again. And again, and again, until you hit a StackOverflowException.
From Adam Maras' answer:
This leads me to believe (without much knowledge of the internals of the runtime binder) that it's proactively checking for recursive constraints, but only one level deep.
It's almost the opposite, in that the problem is proactively setting the base class in such a way as to prevent it realising it already has a type it needs. I think I managed to fix it today though it remains to be seen if someone sees some problem with that fix I missed (a good thing about contributing to the framework is they have a high standard of code reviews, but that of course means I can't be sure a contribution will be accepted until it's in).
Here's my situation. In Java I can mark a method as final in the base/super class and there is no way a derived class can mask a method of the same signature. In C# however, the new keyword allows someone inheriting my class to create a method with the same signature.
See my example below. I need to keep the orignal.MyClass public so please don't suggest that as an answer. This seems to be a lost feature moving from Java to C#:
public class orignal.MyClass{
public void MyMethod()
{
// Do something
}
}
class fake.MyClass: orignal.MyClass {
// How to prevent the following
public new void MyMethod()
{
// Do something different
}
}
EDIT: Not a duplicate.
All answers seem to suggest, it's not possible to prevent a method from being hidden/shadowed in a derived class. This became apparent while migrating some old Java code to C#. A final method in Java will not let anybody use the same method signature in any derived class. While it's great in most scenarios that C# allows a method of same signature in the derived class, it would have been great to prevent such a behavior if warranted.
// How to prevent the following
There is no way to prevent this. It's allowed by the language.
Note that, in practice, this rarely matters. If you expect your base class to be used as your class, your method will still be called. Using new only hides the method when using the DerivedClass from a a variable declared as DerivedClass.
This means that your API, if built around MyClass, will always still call MyMethod when instances are passed into your methods.
Edit in response to comments:
If you are worried about people subclassing your class in general, the only real option you do have would be to seal your class:
public sealed class MyClass
{
This will prevent people from creating a subclass entirely. If you want to allow people to derive from your class, however, there is no way to prevent them from hiding your method in their class.
You can't prevent a public method or property being masked, but why would you? It takes a deliberate action from whoever extends the base class to do this (i.e. they need to type new), so they have intended to do it, why try and stop them?
Maybe you need to switch your pattern up a bit? If the extender must use your base method then you can put something critical in it, thus forcing them to call it. Of course this is smelly if not done correctly, so if you use this approach then mark your method as virtual, then in the documentation (or method header comments) mention that the base method must be called. This way you avoid the extender having to hide/mask your method (although they still could), but they can still extend it if they want.
I'm assuming you really want to prevent someone from overriding the method - hiding a method with new cannot be prevented, but it poses no risk to the base class, so that shouldn't be an issue.
In C# methods are not overrideable by default. So you can simply prevent someone form overriding a base method by not marking it virtual or abstract. In Java methods are virtual by default, so sealing a method by using final is necessary to prevent overriding.
I think the only way is to create interface the put your method definition within it, then let the original class to implement the interface and implement the method explicitly:
interface IAnimal
{
string diary(string notes, int sleephours);
}
class Dogs:IAnimal
{
virtual public string voice()
{
string v = "Hao Hao"; return v;
}
string IAnimal.diary(string notes,int sleephours)
{
return notes + sleep.ToString() + " hours";
}
}
class Cats:Dogs
{
public override string voice()
{
string v = "Miao Miao"; return v;
}
}
You will not use diary() method via Cats instance.
For prevent of hiding base class method you can do like this:
public class Org
{
public void Do()
{
// do something
}
}
public class Fake : Org
{
public new void Do()
{
base.Do();
// do something
}
}
here the base keyword refers to Father class.
now you called method from Father class (here is Org) in child class and now this method doesnt hide anymore.
Why is overloading called compile time polymorphism and Overriding run time polymorphism in C#?
Well, overloading decisions (which method signatures are used, based on the arguments1) are made by the compiler, whereas overriding decisions (which method implementations are used, based on the type of the target of the method) are made by the CLR at execution time.
I wouldn't usually call overloading "polymorphism" though. In my experience the word usually refers to overriding. I suppose overloading does allow you to treat an object of one type as another, although overloading itself doesn't need to be involved there - it's just normal type conversions.
Here's an example showing that overload choice is performed at compile time:
using System;
class Test
{
static void Foo(object a)
{
Console.WriteLine("Object overload called");
}
static void Foo(string a)
{
Console.WriteLine("String overload called");
}
static void Main()
{
object x = "hello";
Foo(x);
}
}
Here the Foo(object) overload is called because x is of type object at compile time - it's only at execution time that it's known to refer to a string.
Compare that with this example:
using System;
class Base
{
public virtual void Foo()
{
Console.WriteLine("Base.Foo called");
}
}
class Derived : Base
{
public override void Foo()
{
Console.WriteLine("Derived.Foo called");
}
}
class Test
{
static void Main()
{
Base x = new Derived();
x.Foo();
}
}
Here the compile-time type of x is Base, but it's still the derived class's overriding method which is called, because the execution-time type of the object that x refers to is Derived.
1 It's slightly more complicated than that in fact, due to method hiding etc - but in simple cases you can think of it as just picking the signature.
Overridden functions are functions that have the same signature, but are implemented in different derived classes. At compile time, usually the base class type is used to reference an object, though at run time this object could be of a derived type, so when an overridden method is called, the implementation that is called is dependent on what kind of object is doing the calling (base vs. a derived type) which is unknown at compile time.
Overloading (not really polymorphism) is simply multiple functions which have the same name but different signatures (think multiple constructors for an object taking different numbers of arguments). Which method is called is known at compile time, because the arguments are specified at this time.
Polymorphism
Through inheritance, a class can be used as more than one type; it can be used as its own type, any base types, or any interface type if it implements interfaces. This is called polymorphism.
Polymorphism means having more than one form. Overloading and overriding are used to implement polymorphism. Polymorphism is classified into compile time polymorphism or early binding or static binding and Runtime polymorphism or late binding or dynamic binding.
Overriding - same method names with same arguments and same return types associated in a class and its subclass. Overriding in C# makes use of the "override" keyword. To override a method means to replace it with a new way of handling data.
Overloading - same method name with different arguments, may or may not be same return type written in the same class itself.
Compile time Polymorphism or Early Binding
The polymorphism in which compiler identifies which polymorphic form it has to execute at compile time it self is called as compile time polymorphism or early binding.
Advantage of early binding is execution will be fast. Because every thing about the method is known to compiler during compilation it self and disadvantage is lack of flexibility.
Examples of early binding are overloaded methods, overloaded operators and overridden methods that are called directly by using derived objects.
Runtime Polymorphism or Late Binding
The polymorphism in which compiler identifies which polymorphic form to execute at runtime but not at compile time is called as runtime polymorphism or late binding.
Advantage of late binding is flexibility and disadvantage is execution will be slow as compiler has to get the information about the method to execute at runtime.
Example of late binding is overridden methods that are called using base class object.
class A
{
public virtual void Leg(string Name)
{
}
}
class B:A
{
public override void Leg(string Name)
{
}
}
Example for Over loading
class A
{
void a()
{
}
void a(string Name)
{
}
}
In other words, "Many forms of a single object is called Polymorphism."
Eg:
A Team Leader behaves to Sub Ordinate.
A Team Leader behaves to his/her seniors.
A Team Leader behaves to other Team Leaders.
Here Team Leader is an object but attitude is different in different situation.
Difference between Method Overriding and Method hiding
Method overriding allows a subclass to provide a specific implementation of a method that is already provided by base class. The implementation in the subclass overrides (replaces) the implementation in the base class.
The important thing to remember about overriding is that the method that is doing the overriding is related to the method in the base class.
When a virtual method is called on a reference, the actual type of the object to which the reference refers is used to determine which method implementation should be used. When a method of a base class is overridden in a derived class (subclass), the version defined in the derived class is used. This is so even should the calling application be unaware that the object is an instance of the derived class.
Method hiding does not have a relationship between the methods in the base class and derived class. The method in the derived class hides the method in the base class.
compile time polymorphism
Suppose lets say you have 2 methods as follows; since the method shares same name but have different parameters; it is called as "overloaded" method.
Eat(string food);
Eat(string food, string SpoonOrFork);
and you are using like this in your dinner class
public class Man
{
public bool Eat (string food)
{
//implementation
}
public bool Eat (string food, string SpoonOrFork)
{
//implementation
}
}
public class dinner
{
public bool Start()
{
string food = "course1";
Man.Eat ( food);
}
}
Now when you compile this program the compiler knows exactly which version of Eat method to call during compile time itself (because of the difference in parameters).
That's why it is called as compile time polymorphism.
Run time polymorphism
public class chimp
{
public virtual void walk()
{
Console.WriteLine("I am walking using 4 legs");
}
}
public class neanderthals : chimp
{
public override void walk()
{
Console.WriteLine("I am walking using 2 legs");
}
}
class Program
{
static void Main(string[] args)
{
chimp x = new neanderthals();
x.walk();
Console.ReadLine(); // this will give an output of "I am walking using 2 legs"
}
}
In the above code x is of type chimp. Even though the compiler thinks it is going to call the walk method in chimp; but that is not what actually happens. Since it depends on CLR (run time) this kind of polymorphism is called "run-time" polymorphism.
Polymorphism
Polymorphism means many forms (ability to take more than one form). In Polymorphism poly means “multiple” and morph means “forms” so polymorphism means many forms.
In polymorphism we will declare methods with same name and different parameters in same class or methods with same name and same parameters in different classes. Polymorphism has ability to provide different implementation of methods that are implemented with same name.
In Polymorphism we have 2 different types those are
- Compile Time Polymorphism (Called as Early Binding or Overloading or static binding)
- Run Time Polymorphism (Called as Late Binding or Overriding or dynamic binding)
Compile Time Polymorphism
Compile time polymorphism means we will declare methods with same name but different signatures because of this we will perform different tasks with same method name. This compile time polymorphism also called as early binding or method overloading.
Method Overloading or compile time polymorphism means same method names with different signatures (different parameters)
For more details check this link polymorphism in c#
Run Time Polymorphism
Run time polymorphism also called as late binding or method overriding or dynamic polymorphism. Run time polymorphism or method overriding means same method names with same signatures.
In this run time polymorphism or method overriding we can override a method in base class by creating similar function in derived class this can be achieved by using inheritance principle and using “virtual & override” keywords.
Compile time Polymorphism
Compile time Polymorphism is also known as method overloading.
Method overloading means having two or more methods with the same name but with different signatures.
Run time Polymorphism
Run time Polymorphism is also known as method overriding.
Method overriding means having two or more methods with the same name and same signature, but with a different implementation
Run time Polymorphism Example in c#.
using System;
public class demo{
public static void Main(String[] args){
cal cal ;
add a = new add();
cal = a;
Console.WriteLine("Addition is" + cal.calculate(20, 20));
sub s = new sub();
cal = s;
Console.WriteLine("Substraction is" + cal.calculate(20, 20));
mul m = new mul();
cal = m;
Console.WriteLine("Multiplication is" + cal.calculate(20, 20));
div d = new div();
cal = d;
Console.WriteLine("Division is" + cal.calculate(20, 20));
Console.ReadLine();
}
}
public abstract class cal{
public abstract int calculate(int a, int b);
}
public class add : cal {
public override int calculate(int a ,int b){
return a+b;
}
}
public class sub : cal{
public override int calculate(int a, int b){
return a-b;
}
}
public class mul : cal{
public override int calculate(int a, int b){
return a*b;
}
}
public class div : cal{
public override int calculate(int a, int b){
return a/b;
}
}
Because it's known at compile time which of your overloaded functions is called, but that is not always the case for an overridden function.
Classical examples of static polimorphism are based on template metaprogramming or Duck Typing but not on method overloading.
Static polimorphism means that desicion is made by compilier (statically), and dynamic polimorphism means that desition is made only in runtime (dynamically).