For the following code:
class B
{
public String G() { return "B.G()"; }
}
class D : B
{
public String G() { return "D.G()"; }
}
class TestCompile
{
private static String TestG<T>(T b) where T: B
{
return b.G();
}
static void Main(string[] args)
{
TestG(new D());
}
}
The result is B.G()
, whereas the result of similar C++ code would be D.G()
.
Why is there this difference?
base (C# Reference) The base keyword is used to access members of the base class from within a derived class: Call a method on the base class that has been overridden by another method. Specify which base-class constructor should be called when creating instances of the derived class.
In the same way, you can derive a generic class from another generic class that derived from a generic interface. You may be tempted to derive just any type of class from it. One of the features of generics is that you can create a class that must implement the functionality of a certain abstract class of your choice.
A method declared with the type parameters for its return type or parameters is called a generic method. Above, the AddorUpdate() and the GetData() methods are generic methods. The actual data type of the item parameter will be specified at the time of instantiating the DataStore<T> class, as shown below.
Use the override keyword:
class B
{
public virtual String G() { return "B.G()"; }
}
class D : B
{
public override String G() { return "D.G()"; }
}
Without the override keyword, the inherited method doesn't replace the base one.
Without override:
D obj = new D();
obj.G(); // "D.G()"
((B)obj).G(); // "B.G()"
With override:
D obj = new D();
obj.G(); // "D.G()"
((B)obj).G(); // "D.G()"
C# generics are compiled only once: at the time the generic is compiled. (Think about it: C# lets you use List<T>
without seeing its implementation.) Here, it sees from the where T: B
clause that the parameter is a B
, so it calls B.G
.
C++ templates are compiled each time they are invoked. When you type TestG<D>()
, a brand new copy of TestG
is compiled with T = D
. At invocation time, the compiler sees that D
has its own G
method and calls it.
The C++ equivalent of the C# generic would be
template<typename T>
string TestG(T t)
{
B& b = static_cast<B&>(t); // force `t` into a `B`
return b.G();
}
The remarks of others regarding the use of virtual
apply equally to C# and C++. I'm just explaining why C++ behaves differently from C#.
Becuase you've neglected to mark B.G
as virtual
, and D.G
as override
.
You got this compiler warning:
CS0108: 'D.G()' hides inherited member 'B.G()'. Use the new keyword if hiding was intended.
but you chose to ignore it. I would expect better from a C++ developer! :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With