简体   繁体   English

尝试创建 C# 方法,该方法输出嵌套在另一个泛型类型中的泛型类型的 object

[英]Trying to create C# method that outputs an object of a generic type that's nested inside another generic type

I'm currently working on writing a method that, for the sake of this problem, generates mazes.我目前正在编写一种方法,为了解决这个问题,它会生成迷宫。

Here's the (simplified) version of the classes involved:这是所涉及的类的(简化)版本:

public interface IAlgorithm<out MazeType> where MazeType : Maze
{
    MazeType GoGenerate();
}
public class AlgorithmBacktrack : IAlgorithm<Maze>
{
    public Maze GoGenerate()
    {
        //Do things
        return new Maze();
    }
}
public class Maze
{
}

public class MazeWithPath : Maze
{
}

What I'd like to do now is create helper to call this Algorithm:我现在想做的是创建助手来调用这个算法:

public class MazeGenerator
{
    public static MAZETYPEGENERIC Generate<AlgorithmType>()
        where AlgorithmType : IAlgorithm<MAZETYPEGENERIC>, new()
    {
        var alg = new AlgorithmType();
        return alg.GoGenerate();
    }
}

The thing that I can't get to work though is the MAZETYPEGENERIC.不过,我无法开始工作的是 MAZETYPEGENERIC。 Theoretically C# could know that whatever interface implementation of IAlgorithm I put in there would have the MAZETYPEGENERIC configured.从理论上讲,C# 可以知道我放在那里的任何 IAlgorithm 接口实现都会配置 MAZETYPEGENERIC。 However C# still want's me to add that as a Generic parameter to the method.但是 C# 仍然希望我将其作为通用参数添加到方法中。 Eg:例如:

public static MAZETYPEGENERIC Generate<AlgorithmType, MAZETYPEGENERIC>()
    where AlgorithmType : IAlgorithm<MAZETYPEGENERIC>, new()
    ...

This however would mean that the invocation of this call would also require this parameter.然而,这意味着调用此调用也需要此参数。 Even though it could theoretically be inferred from the AlgorithmType.尽管理论上可以从 AlgorithmType 推断出来。

//Ideal way to call this method:
Maze m = MazeGenerator.Generate<AlgorithmBacktrack>();

//Actual way to call this after adding the additional generic parameter:
Maze m = MazeGenerator.Generate<AlgorithmBacktrack, Maze>();

I would love to see/hear if someone has an idea on how to accomplish option 1 (the ideal way of doing this).如果有人对如何完成选项 1(执行此操作的理想方式)有想法,我很乐意看到/听到。

One way to do this is to accept an instance of IAlgorithm<MAZETYPEGENERIC> , and let type inference infer the type parameter MAZETYPEGENERIC .一种方法是接受IAlgorithm<MAZETYPEGENERIC>的实例,并让类型推断推断类型参数MAZETYPEGENERIC Now you wouldn't need the AlgorithmType type parameter现在您不需要AlgorithmType类型参数

Maze m = MazeGenerator.Generate(new AlgorithmBacktrack());

...

public static MAZETYPEGENERIC Generate<MAZETYPEGENERIC>(IAlgorithm<MAZETYPEGENERIC> algorithm)
    where MAZETYPEGENERIC : Maze {
    return algorithm.GoGenerate();
}

You would have been able to access the type parameter of IAlgorithm if C# interfaces used associated types (like Swift), rather than generics.如果 C# 接口使用关联类型(如 Swift)而不是 generics,您能够访问IAlgorithm的类型参数。 So it's not like this is completely impossible feature to have in a language.因此,这并不是一种语言中完全不可能的功能。 For a comparison see this post .比较看这篇文章

If "instantiate the Algorithm class" is all you need, the closest I can get is probably by moving the call to GoGenerate method out of Generate method, like this:如果您只需要“实例化算法类”,那么我能得到的最接近的可能是将GoGenerate方法的调用移出Generate方法,如下所示:

static T Generate<T>() where T : IAlgorithm<Maze>, new()
{
    return new T();
}

Maze m = MazeGenerator.Generate<AlgorithmBacktrack>().GoGenerate();
// I made the algorithm class up
MazeWithPath m = MazeGenerator.Generate<AlgorithmBacktrack2>().GoGenerate();

Or if the type of local variable m is always Maze , you could also do something like:或者,如果局部变量m的类型始终是Maze ,您还可以执行以下操作:

static Maze Generate<T>() where T : IAlgorithm<Maze>, new()
{
    return new T().GoGenerate();
}

Also want to comment on也想评论

Theoretically C# could know that whatever interface implementation of IAlgorithm I put in there理论上 C# 可以知道我放在那里的任何 IAlgorithm 接口实现

I hope C# would not (like it currently does).我希望 C# 不会(就像现在一样)。 T in your case is covariant .在您的情况下, Tcovariant If T is implementation of IAlgorithm<MazeWithPath> , both Maze , MazeWithPath and object are semantically correct for return type.如果TIAlgorithm<MazeWithPath>的实现,则MazeMazeWithPathobject在语义上对于返回类型都是正确的。

The compiler can't choose one without knowing the context of your code.编译器无法在不知道代码上下文的情况下选择一个。 And if it can, it may choose a wrong one for you:如果可以,它可能会为您选择错误的:

// This is only correct when the compiler chooses MazeWithPath as return type
// It will become invalid if compiler chooses Maze or object
MazeWithPath m = Generate<AlgorithmBacktrack2>();

In saying that, making Generate method to take two generic parameters might make more sense IMO.话虽如此,使Generate方法采用两个通用参数可能更有意义 IMO。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 c# - 将一种对象类型转换为另一种对象类型的通用自定义方法 - Generic custom method to convert one object type to another in c# C#-泛型类中的特定类型方法声明 - C# - specific type method declaration inside a generic class 在 C# 中,如何在方法内实例化传递的泛型类型? - In C#, how to instantiate a passed generic type inside a method? 在C#中将对象显式地转换为泛型类型的另一个对象,该对象仅在运行时可用 - Explicitly casting an object to another object of a generic type in C# that's available only at runtime 在c#中将一个任意类型转换为另一个类型的通用方法 - Generic method to cast one arbitrary type to another in c# 在部分类上创建多态方法以在C#上发送泛型类型 - Create Polymorphic method on partial class to send generic type on c# C#泛型:将通用类型与另一类相匹配的更好方法是什么? - C# Generics: Better Way to Match the Generic's Type to Another? 我可以在C#中将对象强制转换为其通用类型吗? - can I cast an object to it's generic type in C#? 使用“泛型”方法创建接口,但泛型类型是接口的实现者 - Create an interface with a method that's 'generic', but it's generic type is the implementer of the interface 在C#中的Generic类中获取嵌套泛型类的类型 - Get Type of a nested Generic class in a Generic class in C#
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM