如何正确处理由泛型类组成的列表,其方法也具有泛型返回值
本文关键字:方法 返回值 泛型 列表 理由 处理 何正确 泛型类 | 更新日期: 2023-09-27 17:51:12
我相信这个问题的答案很简单,但由于我一直在思考这个问题,我可能很难看到整体情况。
我想加载多个文件(在本例中是JSON),所以我创建了一个DataLoader
类来处理这个问题。在这个类中,我正在创建一个ILoaders
列表,该类将迭代和加载,以便在将来如果我使用JSON以外的东西,抽象将已经实现。
public class DataLoader{
private List<IDataLoaded> allDataLoaded = new List<IDataLoaded>();
private List<ILoader> loaderLists = new List<ILoader> (){
new JSONLoader<RootSpacecrafts>(),
new JSONLoader<RootWeapons>()
};
public void LoadData(){
foreach(ILoader loader in loaderLists){
loader.Read ();
IDataLoaded dataLoaded = loader.Load ();
allDataLoaded.Add(dataLoaded);
}
}
}
当我创建我的JSONLoader
类并使其实现ILoader
接口时,我注意到我必须将ILoader
转换为通用接口:我将始终需要提供JSONLoader
将放入数据的根类T
,并且还需要它灵活并返回包含加载数据的List<T>
。
所以现在我的JSONLoader
类读为:
public class JSONLoader<T> : ILoader<T> where T : IDataLoaded, new(){
private string fileContents;
private T output = new T();
private List<T> outputlist;
public void Read(){
fileContents = File.ReadAllText(Paths.Get(output.Descriptor));
outputlist = JsonConvert.DeserializeObject<List<T>>(fileContents);
}
public List<T> Load(){
return outputlist;
}
}
和illoader:
public interface ILoader<T>{
void Read();
List<T> Load();
}
现在当我回到DataLoader
类时,正如您所看到的,我失去了调用ILoader
的灵活性,因为我需要告诉正在使用的泛型类是什么。
我试图将其封装在另一个接口中,但随后DataLoader
中的loader.Load()
调用被打破,因为它返回List<T>
。
现在我的感觉是,要修好一边,就得弄坏另一边。我一直在努力思考抽象类和接口的良好组合,以相应地隔离所有内容,但我在可视化中遇到了一个大麻烦(我对c#相当陌生,还没有头脑敏捷地看到我应该做什么和封装)。
我将此作为学习c#的练习,并希望尽可能使用最佳编程实践。我想有一个健壮的代码,没有重复和类之间的依赖最小的数量。我也希望得到一个解释,而不仅仅是一个工作代码。谢谢你!
我对接口有一些问题(它抱怨它不能将JSONLoader表达式转换为类型ILoader)
这是因为List<T>
不是协变的。如果你想让它工作,而不是暴露List<T>
,你可以暴露IEnumerable<T>
,它是T
的协变,也使你的Loader<T>
与Loader<out T>
协变:
public class DataLoader
{
private IEnumerable<IDataLoaded> allDataLoaded = new List<IDataLoaded>();
private IEnumerable<ILoader<IDataLoaded>> loaderLists = new
List<ILoader<IDataLoaded>>
{
new JsonLoader<RootSpacecrafts>(),
new JsonLoader<RootWeapons>()
};
public void LoadData()
{
foreach (ILoader<IDataLoaded> loader in loaderLists)
{
loader.Read();
allDataLoaded = loader.Load();
}
}
}
public interface ILoader<out T>
{
void Read();
IEnumerable<T> Load();
}
public class JsonLoader<T> : ILoader<T> where T : IDataLoaded, new()
{
private string fileContents;
private T output = new T();
private IEnumerable<T> outputlist;
public void Read()
{
fileContents = File.ReadAllText("");
outputlist = JsonConvert.DeserializeObject<List<T>>(fileContents);
}
public IEnumerable<T> Load()
{
return outputlist;
}
}