How to get an argument of a common base class at compile time? (i.e. without using reflection)

I want to implement a general method for retrieving header / detail data from a database:

public static T RetrieveHeaderDetail<T> where T : Header<???>, new() // Where ??? means "what can I do here?" { // ... } 

Here is a description of the general view representing the title of the document:

 public class Header<TDetail> where TDetail : class, new() { public List<TDetail> Details; } 

And here are a few instances:

 public class RequestForQuotation : Header<RequestForQuotationDetail> { ... } public class Order : Header<OrderDetail> { ... } public class Invoice : Header<InvoiceDetail> { ... } // .. 

It is easy to prove that since .NET does not allow multiple inheritance or “general specialization” (which would allow Header<U> to derive from some other Header<V> ), for any particular T there is at most one U , so T inherits ( directly or indirectly) from Header<U> . Moreover, it is trivial to find type U : iterate over the base types of T until you find an instance of Header<U> , and then just take a general argument! However, C # wants me to point out a change in my method definition to the following:

 public static T RetrieveHeaderDetail<T,U> where T : Header<U>, new() where U : class, new() { // ... } 

Is there any way around this problem? I know that it would be possible to use Reflection, but I believe that at runtime it is not recommended to do what could be done at compile time.


When I run into such problems, I really miss C ++.

+4
source share
2 answers

I asked this question not so long ago.

Generics with general parameters and abstract class

+1
source

I'm not sure I fully understand what you need, but could you define an interface and use it to indicate a constraint?

For example, we have something like this in several places:

 public class Reader<T> where T : IInt32Id { public T GetById(int Id) { // get by id } } 

Then I just use the IInt32Id interface as an interface to output all my classes that have an ID index (as opposed to a long one).

0
source

All Articles