简体   繁体   中英

C# Generics - Determine generic type from consuming generic method

Long story: I'm working on a system that will have Tasks and Handlers . Tasks will be sent from disparate parts of the system to the Handlers, where they will eventually return a value.

We've got a system in-place that is loosely-typed and has turned into something of a gnarled mess (the problem is significantly amplified by the fact that the task-initiators are often coming from third-party components that are essentially plug-ins).

I've been thinking of ways to implement the same in a strongly-typed fashion--and might just be taking this to the point of obsurdity--but am close to what I'd like . The problem is some syntax.

Here's what I've got (generic names expanded for clarity):

interface ITask<ReturnType> { }

interface ITaskHandler<TaskType, TaskReturnType> where TaskType : ITask<TaskReturnType>
{
    TaskReturnType PerformTask(TaskType task);
}

As you can see, ITask is generic, and the declared generic parameter for ITask is the return-type for ITaskHandler<ITask> . This means that each TaskHandler is contractually bound to return the type specified by its ITask .

The big downside that declaring TaskHandlers leads to some fairly ugly Signatures...

class SpecificTask : ITask<Dictionary<Type,Delegate>>
{
}

class SpecificHandler : ITaskHandler<SpecificTask, Dictionary<Type, Delegate>>
{
    public Dictionary<Type, Delegate> PerformTask(SpecificTask task)
    {
        return new Dictionary<Type, Delegate>();
    }
}

My question is: since SpecificTask has already provided it's ReturnType as a generic parameter, can SpecificHandler 's signature be shortened to something more like:

interface ITaskHandler<TaskType> where TaskType : ITask
{
    // pulling TaskReturnType out of thin air...
    TaskReturnType PerformTask(TaskType task);
}

class SpecificHandler : ITaskHandler<SpecificTask>
{
    public Dictionary<Type, Delegate> PerformTask(SpecificTask task)
    {
        return new Dictionary<Type, Delegate>();
    }
}

...and if so, how would I declare the return type of PerformTask when the type is contained within SpecificTask ?

Unfortunately you can't do what you want to do and retain static type checking. All of the generic type parameters must be delared in order for the compiler to be able to statically know what goes where.

You could do this with reflection but that would completely undermine the purpose of generics in the first place.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM