Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C#: Add conditional generic method (different generic restriction) within generic class

Tags:

c#

linq

I'm trying to add another restriction on a method within a generic class. Is this possible?

Pseudocode:

public class MyBaseClass<T> where T: class
{
    public IQueryable<T> ShowThisMethod where T: class, IMyInterface
    {
         // stuff.
    }
}

ShowThisMethod should only be available when T is IMyInterface. Also IMyInterface should then give information back (about T) so that I can access properties defined in IMyInterface inside of the method.

Help :)

By the way, this compiles (and seems "almost right"):

public class MyBaseClass<T> where T: class
{
    public IQueryable<T> ShowThisMethod<T>() where T: class, IMyInterface
    {
        String X = T.MyInterfaceStringProperty;
    }
}

More Information about my goal:

I'm using a generic base class to access a common property (DateTime "Time" property on LINQ object Dinner which is also on Lunch).

Both objects are implementing ITimeable which exposes the DateTime property.

In my base class I'd like to have a method Select() which works on IQueryable&ltT> and can automatically filter based on the Time property. Because I'm working off the generic T, the time property is not visible to the base class, unless I tell it that T is implementing ITimeable.

I do want the same base class to work for other non-ITimeable objects too, that's why I need the interface restriction on the Select method, and I also need it in order to access the Time property using generics.

Hope that clears the goal :)

P.S. My main concern is not visibility of the method in IntelliSense etc.. I'd just like to keep my base class working, while being able to access an interface-specified property through generics in it.

like image 668
Alex Avatar asked Feb 28 '23 16:02

Alex


1 Answers

It depends on what you want.

Since the class is compiled once, and the magic with generics also relies on the runtime, there's no way to make a class that has some methods in some cases, and other methods in other cases. Either the methods are there, or they aren't.

So basically, there's no way to declare MyBaseClass so that the following happens:

MyBaseClass<Int32>  bc;
bc. <-- intellisense does not show ShowThisMethod here

MyBaseClass<SomeTypeImplementingIMyInterface> bc2;
bc2. <-- intellisense DOES show ShowThisMethod here

... that is... by itself.

You can "trick" the compiler and intellisense into giving you what you're asking for, but know that this gives you other limitations and challenges that might need to be solved.

Basically, by adding an extension method to a static class declared alongside MyBaseClass, you can make intellisense, and the compiler, behave as if the method is only present for MyBaseClass when T has some specific rules, as you're asking for.

However, since the method in question will be a static method, defined outside of MyBaseClass, there's limits to how much of the internals of MyBaseClass you can access, and you can't access the method inside MyBaseClass, so it depends on what you want to accomplish and whether you can live with the limitations or not.

Anyway, here's the extension method. Note that you remove it completely from MyBaseClass at the same time:

public static class MyBaseClassExtensions
{
    public static IQueryable<T> ShowThisMethod<T>(this MyBaseClass<T> mbc)
        where T: class, IMyInterface
    {
        ...
    }
}
like image 139
Lasse V. Karlsen Avatar answered Apr 27 '23 06:04

Lasse V. Karlsen