C#泛型工厂调用报错:ImageResource无法转换为Resource<ResourceObject>如何解决
问题根源
- 你遇到的是C#泛型的不变性限制:泛型类默认不支持协变,就算
Image是ResourceObject的子类,Resource<Image>也不会自动视为Resource<ResourceObject>的派生类,所以不符合Get<T>()方法里T : Resource<ResourceObject>的约束。
可行的修复方案
有两种常用改法,可按需选择:
方案1:给工厂方法加双层泛型参数,对应资源类和资源对象类型
不需要修改原有基类定义,兼容性最好:
public class RemoteResourcesFactory : ResourcesFactory { // TResource为资源类类型,TObject为返回的资源对象类型 public static TResource Get<TResource, TObject>() where TResource : Resource<TObject>, new() where TObject : ResourceObject { TResource resource = new TResource(); resource.payload = load(resource.resType, resource.path); return resource; } }
调用时传入对应泛型参数即可:
Image image = RemoteResourcesFactory.Get<ImageResource, Image>().GetFirst();
方案2:新增非泛型Resource基接口,作为工厂的约束类型
原有调用代码不需要修改:
- 先定义非泛型接口,让泛型Resource基类实现该接口:
public interface IResource { Type resType { get; } string path { get; } } public abstract class Resource<T> : IResource where T : ResourceObject { protected string path = "base"; public IEnumerable<T> payload; public Type resType = typeof(T); string IResource.path => path; Type IResource.resType => resType; public T GetFirst() { return payload.First(); } }
- 修改工厂方法的约束规则:
public class RemoteResourcesFactory : ResourcesFactory { public static T Get<T>() where T : IResource, new() { T resource = new T(); resource.payload = load(resource.resType, resource.path); return resource; } }
补充说明
原有架构设计思路是合理的,只是踩到了C#泛型默认不变的语法限制,不需要整体推翻重构。
内容的提问来源于stack exchange,提问作者Dmitry K.
相关产品推荐
相关产品推荐

