这可能是一个概念上的误解,但我想知道为什么。
我有一个静态方法,它可以返回一个泛型值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
。这也不起作用,因为ActionType
和WordType
是独立的类型,枚举不允许继承,这可能会使其他返回类型起作用。
如果您在编译时不能知道返回类型,那么您必须返回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);
}