如何解决使用泛型方法时如何正确约束相关类类型?
我有两个基类 BaSEObject
和 BaSEObjectSettings
。第一个定义对象行为,第二个定义类的状态(用于序列化)。
如果我想创建具有特定设置的派生 BaSEObject 类,那么我可以使用具有泛型类型约束的方法。
public void CreateBaSEObjectInstance<T>(BaSEObjectSettings baSEObjectSettings) where T : BaSEObject
{
var instance = pool.GetInstance<T>();
instance.Settings = baSEObjectSettings;
scene.Add(instance);
}
我面临的问题是,虽然我可以将泛型类型限制为 BaseClass,但无法将 BaseClassSettings 限制为相关的派生 BaseClass。这意味着我可以做诸如
之类的事情CreateBaSEObjectInstance<Banana>(new AppleSettings());
这看起来有点可怕。
鉴于我目前被限制在将对象添加到场景之前以相同的方法创建和初始化对象,我有哪些选择?
解决方法
一种方法是让所有设置类都继承自通用基类。通用基类可以从 BaseObjectSettings
继承。泛型类型参数指示此设置类适用于哪种对象。
例如,对于您的 AppleSettings
,
class AppleSettings: ObjectSettings<Apple> {
...
}
abstract class ObjectSettings<T>: BaseObjectSettings where T: BaseObject {}
现在,您可以更改 CreateBaseObjectInstance
以接受 ObjectSettings<T>
的实例:
public void CreateBaseObjectInstance<T>(ObjectSettings<T> objectSettings) where T : BaseObject
{
var instance = pool.GetInstance<T>();
instance.Settings = objectSettings;
scene.Add(instance);
}
如果您将 Banana
作为 T
传递,它会期望 ObjectSettings<Banana>
,从而阻止您给它 AppleSettings
,即 ObjectSettings<Apple>
。
我不太明白这里的逻辑,因为缺少一些东西,但是从提供的代码中您可能可以编写:
public void CreateBaseObjectInstance<TBase,TSettings>(TSettings baseObjectSettings)
where TBase : BaseObject
where TSettings : BaseObjectSettings
这样使用:
CreateBaseObjectInstance<Banana,AppleSettings>(new AppleSettings());
可以改进为:
public void CreateBaseObjectInstance<TBase,TSettings>(TSettings baseObjectSettings)
where TBase : BaseObject
where TSettings : BaseObjectSettings,new()
{
if ( baseObjectSettings == null ) baseObjectSettings = new TSettings();
...
}
CreateBaseObjectInstance<Banana,AppleSettings>();
但如果实体和设置之间存在强耦合,您应该重新设计以使用与@Sweeper 和@Moho 的答案类似的事物来定义具有关联的依赖关系:
Association,Composition and Aggregation in C#
Understanding the Aggregation,Association,Composition
,您需要创建一个通用接口或基类来定义设置类型:
public class BaseObject<TSettings>
{
public TSettings Settings { get; set; }
}
那么您的方法将需要两个通用参数 - 一个用于创建 TObject
的实际对象,另一个用于设置 TSettings
的方法参数。然后将 TObject
约束到已实现接口或其基类/派生的实现,使用泛型参数 TSettings
作为约束类型的泛型参数
public void CreateBaseObjectInstance<TObject,TSettings>(
TSettings settings
)
where TObject : BaseObject<TSettings>
{
...
}
示例(使用上面的 BaseObject
实现):
public class MyObjectSettings
{
...
}
public class MyObject : BaseObject<MyObjectSettigns>
{
}
方法调用:
var settings = new MyObjectSettings(){ ... };
CreateBaseObjectInstance<MyObject>( settings ); // second generic argument should be inferred
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。