How to use hiding (new) method with common bounded class

I have a container class that has a generic parameter that is limited to some base class. A type supplied in general is a subclause of the base class constraint. The subclass uses the hiding (new) method to change the behavior of the method from the base class (no, I cannot make it virtual, because this is not my code). My problem is that the "new" methods are not called, the compiler seems to think that the supplied type is a base class, not a sub, as if I had updated it to the base.

It is clear that I misunderstand something fundamental here. I thought the generic where T: xxx was a constraint, not an upcast type.

This sample code basically demonstrates what I'm talking about.

 using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace GenericPartialTest { class ContextBase { public string GetValue() { return "I am Context Base: " + this.GetType().Name; } public string GetOtherValue() { return "I am Context Base: " + this.GetType().Name; } } partial class ContextSub : ContextBase { public new string GetValue() { return "I am Context Sub: " + this.GetType().Name; } } partial class ContextSub { public new string GetOtherValue() { return "I am Context Sub: " + this.GetType().Name; } } class Container<T> where T: ContextBase, new() { private T _context = new T(); public string GetValue() { return this._context.GetValue(); } public string GetOtherValue() { return this._context.GetOtherValue(); } } class Program { static void Main(string[] args) { Console.WriteLine("Simple"); ContextBase myBase = new ContextBase(); ContextSub mySub = new ContextSub(); Console.WriteLine(myBase.GetValue()); Console.WriteLine(myBase.GetOtherValue()); Console.WriteLine(mySub.GetValue()); Console.WriteLine(mySub.GetOtherValue()); Console.WriteLine("Generic Container"); Container<ContextBase> myContainerBase = new Container<ContextBase>(); Container<ContextSub> myContainerSub = new Container<ContextSub>(); Console.WriteLine(myContainerBase.GetValue()); Console.WriteLine(myContainerBase.GetOtherValue()); Console.WriteLine(myContainerSub.GetValue()); Console.WriteLine(myContainerSub.GetOtherValue()); Console.ReadKey(); } } } 

Edit:

I assume that my confusion comes from the fact that you can do it

 class SomeClass<T> where T: AnotherType, new() { T foo = new T(); } 

And I expected T be T , although I understand that the compiler will treat T as having AnotherType interface. I suggested that typing T will happen at run time, even if the T interface was installed at compile time. The declaration of T foo seems misleading here because it really does

 AnotherType foo = new T(); 

As soon as I understand that it does not declare foo as a type T , it is clear why hiding the new method does not work.

And all I have to say about it.

+2
source share
3 answers

The declared new methods are not related (from the point of view of the compiler) to methods with the same name / signature in the base class. This is just a compiler way, allowing you to define different methods in derived classes that share a signature using a method in their base class hierarchy.

Now, for your specific case, understand that generics should compile one set of bytecode regardless of the types that are supplied as common parameters . As a result, the compiler only knows about the method and properties that are defined in the generic type T, which will be the base type specified in the general constraint. The compiler knows nothing about the new methods in the derived type, even if you create an instance of the type type with the derived type as a parameter. Therefore, calls in the general class will always refer to methods of the base type.

There is a lot of confusion regarding the new / virtual / redefinition; take a look at this SO question - Jason and Eric's answers are excellent. Jon Skeet's answer to a similar question can also help you understand why your implementation behaves the way it does.

There are two possible ways to solve this problem:

  • Perform a conditional listing (based on runtime type information) on a derived type (or interface) in your general class. This destroys encapsulation and adds an unwanted connection. It is also fragile if it is performed poorly.
  • Define the interface that you use in your general constraint, which provides methods that interest you. This may not be possible if the code you are extracting from is not something you can change.
+2
source

I think this SO question I asked may help you. See Jon Skeet's answer there for why this is not possible.

+1
source

Add another layer - inherit your generic one not from your third class, but from a new class, which, in turn, is inherited from a third party. In this new class, you can define the method in question as a new virtual one. If all your code never refers to the third part class directly, it should work

+1
source

Source: https://habr.com/ru/post/902645/


All Articles