理解c#中方法中的隐式转换
understanding implicity convertion in method in c#
internal T GetGameObject<T>(int gbId) where T : GameObject
{
return
typeof(T) == typeof(BuildingGameObject) ? buildingGameObjects[gbId] :
typeof(T) == typeof(UnitGameObject) ? unitGameObjects[gbId] :
typeof(T) == typeof(MaterialGameObject) ? materialGameObjects[gbId] :
null;
}
我无法理解为什么我在此处收到 cs0029 错误(无法将类型...BuildingGameObject 隐式转换为 T)(无法将类型...UnitGameObject 隐式转换为 T)(无法将类型隐式转换...MaterialGameObject到 T).
我有一个类似的方法,不会产生错误。
internal V GetComponent<T, V>(int gbId, int componentId) where T : GameObject where V : BaseComponent, IBaseComponent
{
return typeof(T) == typeof(BuildingGameObject) ? buildingGameObjects[gbId].GetComponentById<V>(componentId) :
typeof(T) == typeof(UnitGameObject) ? unitGameObjects[gbId].GetComponentById<V>(componentId) :
materialGameObjects[gbId].GetComponentById<V>(componentId);
}
解决方案?
我发现如果转换 return 值之一(哪个无关紧要)并将其转换为 T 会使错误消失。
internal T GetGameObject<T>(int gbId) where T : GameObject
{
return (T)(
typeof(T) == typeof(BuildingGameObject) ? buildingGameObjects[gbId] :
typeof(T) == typeof(UnitGameObject) ? (GameObject)unitGameObjects[gbId] :
typeof(T) == typeof(MaterialGameObject) ? materialGameObjects[gbId] :
null
);
}
类
internal class BuildingGameObject : GameObject {...}
internal class UnitGameObject : GameObject {...}
internal class MaterialGameObject : GameObject {...}
词典
private readonly Dictionary<int, UnitGameObject> unitGameObjects;
private readonly Dictionary<int, MaterialGameObject> materialGameObjects;
private readonly Dictionary<int, BuildingGameObject> buildingGameObjects;
总而言之,我真的很想了解为什么第一个代码块不起作用,以及当我使用我找到的“解决方案”时会发生什么。
编辑
internal T GetGameObject<T>(int gbId) where T : GameObject
{
return
typeof(T) == typeof(BuildingGameObject) ? (T)buildingGameObjects[gbId] :
typeof(T) == typeof(UnitGameObject) ? (T)unitGameObjects[gbId] :
typeof(T) == typeof(MaterialGameObject) ? (T)materialGameObjects[gbId] :
null
;
}
这给了我 cs0030(无法将类型...BuildingGameObject 转换为 T)(无法将类型...UnitGameObject 转换为 T)(无法将类型...MaterialGameObject 转换为 T)。
首先我会注意到您的代码不是“通用的”。无论输入类型如何,通用代码的工作原理都是一样的——您的代码对三种不同的输入类型做三件不同的事情,对任何其他类型做第四件事(return null
)。事实上,所有类型的代码都非常相似,不意味着它是通用的。
您可以轻松地使用三种不同的方法(GetBuildingGameObject
、GetUnitGameObject
、GetMaterialGameObject
),并且不会遇到这些转换问题。
或者,对 GameObject
的 return 类型使用相同的方法,并让 caller 转换为适当的类型。
但是,要回答这个问题...
编译器在编译时不知道T
是什么类型。您知道(因为您可以阅读代码)T
必须 才能执行该操作,但编译器未被编程为执行该级别静态分析并且知道对象可以是从 BuildingGameObject
到任何 T
的大小写。如果你的核心写得不好,T
可能是 UnitGameObject
,并且没有从 BuildingGameObject
到 UnitGameObject
的转换,所以它会产生错误。
第二种方法有效,因为 GetComponentById<V>
return 是 V
所以它 return 是正确的类型。
您可以通过 explicit cast:
来“确保”编译器对象的类型正确
typeof(T) == typeof(BuildingGameObject) ? (T)buildingGameObjects[gbId]
在您的解决方案中,您正在进行 显式 转换。告诉编译器“我确定转换在 运行 时间有效,因此将其视为有效转换”。在 运行 时间,如果不允许强制转换,您将收到 运行 时间错误。
internal T GetGameObject<T>(int gbId) where T : GameObject
{
return
typeof(T) == typeof(BuildingGameObject) ? buildingGameObjects[gbId] :
typeof(T) == typeof(UnitGameObject) ? unitGameObjects[gbId] :
typeof(T) == typeof(MaterialGameObject) ? materialGameObjects[gbId] :
null;
}
我无法理解为什么我在此处收到 cs0029 错误(无法将类型...BuildingGameObject 隐式转换为 T)(无法将类型...UnitGameObject 隐式转换为 T)(无法将类型隐式转换...MaterialGameObject到 T).
我有一个类似的方法,不会产生错误。
internal V GetComponent<T, V>(int gbId, int componentId) where T : GameObject where V : BaseComponent, IBaseComponent
{
return typeof(T) == typeof(BuildingGameObject) ? buildingGameObjects[gbId].GetComponentById<V>(componentId) :
typeof(T) == typeof(UnitGameObject) ? unitGameObjects[gbId].GetComponentById<V>(componentId) :
materialGameObjects[gbId].GetComponentById<V>(componentId);
}
解决方案? 我发现如果转换 return 值之一(哪个无关紧要)并将其转换为 T 会使错误消失。
internal T GetGameObject<T>(int gbId) where T : GameObject
{
return (T)(
typeof(T) == typeof(BuildingGameObject) ? buildingGameObjects[gbId] :
typeof(T) == typeof(UnitGameObject) ? (GameObject)unitGameObjects[gbId] :
typeof(T) == typeof(MaterialGameObject) ? materialGameObjects[gbId] :
null
);
}
类
internal class BuildingGameObject : GameObject {...}
internal class UnitGameObject : GameObject {...}
internal class MaterialGameObject : GameObject {...}
词典
private readonly Dictionary<int, UnitGameObject> unitGameObjects;
private readonly Dictionary<int, MaterialGameObject> materialGameObjects;
private readonly Dictionary<int, BuildingGameObject> buildingGameObjects;
总而言之,我真的很想了解为什么第一个代码块不起作用,以及当我使用我找到的“解决方案”时会发生什么。
编辑
internal T GetGameObject<T>(int gbId) where T : GameObject
{
return
typeof(T) == typeof(BuildingGameObject) ? (T)buildingGameObjects[gbId] :
typeof(T) == typeof(UnitGameObject) ? (T)unitGameObjects[gbId] :
typeof(T) == typeof(MaterialGameObject) ? (T)materialGameObjects[gbId] :
null
;
}
这给了我 cs0030(无法将类型...BuildingGameObject 转换为 T)(无法将类型...UnitGameObject 转换为 T)(无法将类型...MaterialGameObject 转换为 T)。
首先我会注意到您的代码不是“通用的”。无论输入类型如何,通用代码的工作原理都是一样的——您的代码对三种不同的输入类型做三件不同的事情,对任何其他类型做第四件事(return null
)。事实上,所有类型的代码都非常相似,不意味着它是通用的。
您可以轻松地使用三种不同的方法(GetBuildingGameObject
、GetUnitGameObject
、GetMaterialGameObject
),并且不会遇到这些转换问题。
或者,对 GameObject
的 return 类型使用相同的方法,并让 caller 转换为适当的类型。
但是,要回答这个问题...
编译器在编译时不知道T
是什么类型。您知道(因为您可以阅读代码)T
必须 才能执行该操作,但编译器未被编程为执行该级别静态分析并且知道对象可以是从 BuildingGameObject
到任何 T
的大小写。如果你的核心写得不好,T
可能是 UnitGameObject
,并且没有从 BuildingGameObject
到 UnitGameObject
的转换,所以它会产生错误。
第二种方法有效,因为 GetComponentById<V>
return 是 V
所以它 return 是正确的类型。
您可以通过 explicit cast:
来“确保”编译器对象的类型正确typeof(T) == typeof(BuildingGameObject) ? (T)buildingGameObjects[gbId]
在您的解决方案中,您正在进行 显式 转换。告诉编译器“我确定转换在 运行 时间有效,因此将其视为有效转换”。在 运行 时间,如果不允许强制转换,您将收到 运行 时间错误。