简体   繁体   English

使用泛型的返回类型

[英]Return Type using Generics

First, suggestions for a better title are more than welcome. 首先,提出更好的头衔的建议绝对值得欢迎。

I'm just starting to learn about Generics so my knowledge is kind of limited. 我刚刚开始学习泛型,所以我的知识有限。 What I'm trying to do is return a Type by calling a method without passing any parameters. 我想做的是通过调用方法而不传递任何参数来返回Type。

The part I'm failing at is trying to convert my class to T. 我失败的部分是试图将我的班级转换为T。

Here's my code 这是我的代码

private T ReturnSelectedEvent<T>() where T : BaseEvent
{
    switch (eventList)
    {
        case EventItems.Debug: return (T)((object)typeof(DebugEvent));
    }
    return (T)((object)typeof(BaseEvent));
}

What I want to be returned is the Type so that I may get a static variable in my Class without having to say which class I want it from. 我要返回的是Type,这样我就可以在Class中获得一个静态变量,而不必说我要从哪个类中获取它。 So basically I want to say 所以基本上我想说

DebugEvent.description

Without having to specify the Class, as I have several different of them. 不必指定Class,因为我有几个不同之处。

ReturnSelectedEvent<???>().description

My DebugEvent is a child of BaseEvent and is hiding BaseEvent's description by declaring its own. 我的DebugEvent是BaseEvent的子级,并且通过声明其自身来隐藏BaseEvent的描述。

public class DebugEvent : BaseEvent
{
    public static new string description = "This event will fire a debug message when called";
}

I hope I made myself clear, and that what I'm trying to do is possible. 我希望我能说清楚自己,并且我想做的事情是可能的。

The mess I'm trying to fix with generics is me calling the following multiple times in code. 我试图用泛型解决的麻烦是我在代码中多次调用了以下代码。

case EventItems.ToggleEventHandler: toolTip = ToggleEventHandlerEvent.description; break;
case EventItems.PlayerDamage: toolTip = PlayerDamageEvent.description; break;
case EventItems.ControlRestriction: toolTip = ControlRestrictionEvent.description; break;
case EventItems.PlayerForceMove: toolTip = PlayerForceMoveEvent.description; break;

to something more like this 像这样

toolTip = ReturnSelectedEvent().description;

EDIT: 编辑:

Going to explain a bit more of what I'm after. 我将要解释的更多。

The system above is used for a menu, basically I have a drop down menu from which I select an item. 上面的系统用于菜单,基本上我有一个下拉菜单,从中可以选择一个项目。 The options in this menu are based on an Enum, which is the one called EventItems 此菜单中的选项基于一个枚举,即一个称为EventItems的枚举。

在此处输入图片说明

Now depending on which one I select, I want the description below to match. 现在,根据我选择的内容,我希望下面的描述与之匹配。 The description is saved in the BaseEvent as a static string, which I then hide/"override" in my child event with one that better matches that type of event. 该描述以静态字符串的形式保存在BaseEvent中,然后我在子事件中使用更好地与该事件类型匹配的子事件对其进行隐藏/“覆盖”。

Now my idea is that I could possibly compare the enum and depending on what it is, return the corresponding type so that I may set the proper description. 现在我的想法是,我可以比较枚举,并根据枚举返回相应的类型,以便设置适当的描述。 I then plan on using the same method later. 然后,我计划以后再使用相同的方法。 The following is the current mess I'm stuck in, and I was hoping there would be a way to clear it up 以下是我目前所陷入的混乱,我希望有办法清除它

if (GUILayout.Button("Add to end"))
                    {
                        switch (eventList)
                        {
                            case EventItems.Debug: AddObject<DebugEvent>(); break;
                            case EventItems.Sound: AddObject<SoundEvent>(); break;
                            case EventItems.ToggleEventHandler: AddObject<ToggleEventHandlerEvent>(); break;
                            case EventItems.PlayerDamage: AddObject<PlayerDamageEvent>(); break;
                            case EventItems.ControlRestriction: AddObject<ControlRestrictionEvent>(); break;
                            case EventItems.PlayerForceMove: AddObject<PlayerForceMoveEvent>(); break;
                            case EventItems.CameraFocus: AddObject<CameraFocusEvent>(); break;
                            case EventItems.CameraState: AddObject<CameraStateEvent>(); break;
                            case EventItems.DestroyObject: AddObject<DestroyObjectEvent>(); break;
                            case EventItems.PlayerMoveState: AddObject<PlayerMoveStateEvent>(); break;
                        }
                    }
                    if (GUILayout.Button("Insert before"))
                    {
                        switch (eventList)
                        {
                            case EventItems.Debug: InsertObject<DebugEvent>(loc); break;
                            case EventItems.Sound: InsertObject<SoundEvent>(loc); break;
                            case EventItems.ToggleEventHandler: InsertObject<ToggleEventHandlerEvent>(loc); break;
                            case EventItems.PlayerDamage: InsertObject<PlayerDamageEvent>(loc); break;
                            case EventItems.ControlRestriction: InsertObject<ControlRestrictionEvent>(loc); break;
                            case EventItems.PlayerForceMove: InsertObject<PlayerForceMoveEvent>(loc); break;
                            case EventItems.CameraFocus: InsertObject<CameraFocusEvent>(loc); break;
                            case EventItems.CameraState: InsertObject<CameraStateEvent>(loc); break;
                            case EventItems.DestroyObject: InsertObject<DestroyObjectEvent>(loc); break;
                            case EventItems.PlayerMoveState: InsertObject<PlayerMoveStateEvent>(loc); break;
                        }
                    }
                    if (GUILayout.Button("Insert after"))
                    {
                        switch (eventList)
                        {
                            case EventItems.Debug: InsertObject<DebugEvent>(loc + 1); break;
                            case EventItems.Sound: InsertObject<SoundEvent>(loc + 1); break;
                            case EventItems.ToggleEventHandler: InsertObject<ToggleEventHandlerEvent>(loc + 1); break;
                            case EventItems.PlayerDamage: InsertObject<PlayerDamageEvent>(loc + 1); break;
                            case EventItems.ControlRestriction: InsertObject<ControlRestrictionEvent>(loc + 1); break;
                            case EventItems.PlayerForceMove: InsertObject<PlayerForceMoveEvent>(loc + 1); break;
                            case EventItems.CameraFocus: InsertObject<CameraFocusEvent>(loc + 1); break;
                            case EventItems.CameraState: InsertObject<CameraStateEvent>(loc + 1); break;
                            case EventItems.DestroyObject: InsertObject<DestroyObjectEvent>(loc + 1); break;
                            case EventItems.PlayerMoveState: InsertObject<PlayerMoveStateEvent>(loc + 1); break;
                        }
                        loc++;
                    }
                    if (GUILayout.Button("Replace"))
                    {
                        switch (eventList)
                        {
                            case EventItems.Debug: ReplaceObject<DebugEvent>(); break;
                            case EventItems.Sound: ReplaceObject<SoundEvent>(); break;
                            case EventItems.ToggleEventHandler: ReplaceObject<ToggleEventHandlerEvent>(); break;
                            case EventItems.PlayerDamage: ReplaceObject<PlayerDamageEvent>(); break;
                            case EventItems.ControlRestriction: ReplaceObject<ControlRestrictionEvent>(); break;
                            case EventItems.PlayerForceMove: ReplaceObject<PlayerForceMoveEvent>(); break;
                            case EventItems.CameraFocus: ReplaceObject<CameraFocusEvent>(); break;
                            case EventItems.CameraState: ReplaceObject<CameraStateEvent>(); break;
                            case EventItems.DestroyObject: ReplaceObject<DestroyObjectEvent>(); break;
                            case EventItems.PlayerMoveState: ReplaceObject<PlayerMoveStateEvent>(); break;
                        }
                        loc++;
                    }

I was hoping I could switch out all the different methods to one single one, that would do the same thing, but musch shorter, possibly looking like this instead 我希望我可以将所有不同的方法切换为一个方法,这样做的目的是相同的,但是更短一些,可能看起来像这样

AddObject<ReturnSelectedEvent()>();
InsertObject<ReturnSelectedEvent(loc)>();
AddObject<ReturnSelectedEvent(loc + 1)>();

Hopefully this makes things clearer, also the xxObject methods adds an instantiated Event to a List. 希望这可以使事情变得更清楚,并且xxObject方法也将实例化的Event添加到List。

So what I was thinking is not possible? 所以我在想什么是不可能的? If it isn't, any tips for alternative ways of doing this? 如果不是,是否有其他提示可以替代此方法?

I think you don't want the type but an instance of T . 我认为您不想要类型而是T的实例。 you have to tell your generic method there is a default constructor : 您必须告诉您的通用方法有一个默认的构造函数:

     private T ReturnSelectedEvent<T>() where T : BaseEvent, new()
     {
        return new T();
     }

Then if you want, for example get a DebugEvent you can use : 然后,如果需要,例如获取DebugEvent ,可以使用:

ReturnSelectedEvent<DebugEvent>();

If you really want to use a templated factory, give it a bit more logic. 如果您真的想使用模板化工厂,请给它更多逻辑。 For example, add some parametter in the function that will allow you to switch to null if you're not in debug mode. 例如,在函数中添加一些参数,如果您不在调试模式下,则可以将其切换为null。

this is not possible with generics. 使用泛型是不可能的。

The generic methods are working like a placeholder. 通用方法就像占位符一样工作。 The placeholder has to be filled at the moment of the call. 呼叫时必须填充占位符。 Now your are trying to cast the Type BaseEvent to an instance of type T, which is totally wrong and makes no sense. 现在,您正在尝试将TypeBaseEvent强制转换为T类型的实例,这是完全错误的,没有任何意义。 And the method signature says that the method returns an instance of T (which you should pass on call) --> nonsense. 方法签名表明该方法返回T的实例(您应在调用时传递该实例)->废话。

What you try to do is having inheritance over static properties , this is not possible: 您尝试做的是继承静态属性 ,这是不可能的:

But: What do you have in your EventList? 但是:您的EventList中有什么? Instances of events? 事件实例? Or Types? 还是类型? If instances (which would be way more logic as events are by definition instances) you could do: Create a non-static Getter Method for the events description or an abstract property Description and your problem is solved. 如果实例(按照定义,事件将是更多的逻辑实例),则可以执行以下操作:为事件描述或抽象属性Description创建一个非静态的Getter方法,从而解决了问题。

tooltip = eventList.GetDescription();

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

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