强制转换枚举以返回泛型C#7.3



这可能是一个概念上的误解,但我想知道为什么。

我有一个静态方法,它可以返回一个泛型值T,它还接收一个字符串。

public static T GetWordType<T>(string word) where T : System.Enum
{
if (typeof(T) == typeof(ActionType))
{
foreach (Word<ActionType> action in actionsList)
{
if (action.synonims.Contains(word))
return action.type;
}
return ActionType.None;
}
return WordType.None;
}

所有的返回都会给我一个类型转换错误,标题是"您不能将Action.ActionType隐式转换为T"。

为什么?

声明我的Action类继承了如下定义的抽象Word类:

public abstract class Word<T> where T : System.Enum
{
public List<string> synonims;
public T type;
}

我显然把这件事搞得一团糟,过于复杂了,但我不知道该如何实现。谢谢你的帮助。

编辑:Pavel Anikhouski的请愿书我的ActionType枚举在Action类中声明如下:

class Action : Word<ActionType>
{
public enum ActionType
{
Open, Close, Shutdown, Stop, Send, Save, Load, Move, Add, Cancel, None
}
}

而我的WordType枚举是一个测试枚举,此时可以是任何枚举,只是将其设置为测试不同枚举的返回。类似于:

public enum WordType
{
None, Test
}

当我取出你的if:内部的东西时,看看这个

public static T GetWordType<T>(string word) where T : System.Enum
{
if (typeof(T) == typeof(ActionType))
{ … }
return ActionType.Cancel;
}

如您所见,您可以检查T是否为ActionType。如果是而不是,则返回ActionType.Cancel,它显然是ActionType。但是您的方法应该返回T,您刚刚证明不是ActionType

因此,您实际上希望您的方法在所有情况下都返回ActionType,而不是T,因为这正是您正在做的:

public static ActionType GetWordType<T>(string word) where T : System.Enum
{
if (typeof(T) == typeof(ActionType))
{
foreach (Word<ActionType> action in actionsList)
{
if (action.synonims.Contains(word))
return action.type;
}
return ActionType.None;
}
return ActionType.Cancel;
}

在这一点上,有人可能会说,你甚至不需要一个通用方法,因为除了检查它的确切类型之外,你对参数化类型T并没有做太多的工作。

在泛型方法中处理T的实际可能类型通常是个坏主意。它使您的方法变得脆弱,因为您正在寻找确切的类型,但实际上处理了无限多的类型T,而这些类型是您无法计划的。


此后您更改了问题,使其返回if内部的ActionType.None和条件外部的WordType.None。您仍在返回具体类型,因此无法让方法返回T。这也不起作用,因为ActionTypeWordType是独立的类型,枚举不允许继承,这可能会使其他返回类型起作用。

如果您在编译时不能知道返回类型,那么您必须返回object并在运行时解释结果,以查看它的实际值。


如果您实际上希望返回值WordType.None是枚举类型T的值,那么所能做的就是始终返回枚举的默认值。这样,您就可以使方法具有通用性,并对ActionType:进行自定义处理

public static T GetWordType<T>(string word) where T : System.Enum
{
if (typeof(T) == typeof(ActionType))
{
// you know `T` is `ActionType`, so you can cast to `T`:
return (T)(object)ActionType.None;
}
// since you don’t know `T`, you cannot refer to actual values on
// the imaginary enum `T`; you can however use the default value
// (which will be the value 0, by default the first enum value)
return default(T);
}

相关内容

  • 没有找到相关文章

最新更新