如何使用也具有通用 returns 的方法正确处理由通用 类 组成的列表
How to correctly handle a list made of generic classes with methods that also have generic returns
我认为这个问题的答案很简单,但是由于我一直在这个问题上苦思冥想,所以我可能无法看清全局。
我想加载多个文件(在本例中,JSON),所以我创建了一个 DataLoader
class 来处理这个问题。在这个 class 中,我正在创建一个 ILoaders
的列表,class 将迭代和加载它,以便将来如果我使用 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
class 并使其实现 ILoader
接口时,我注意到我必须将 ILoader
转换为通用接口:我将总是需要提供根 class T
,JSONLoader
将把数据放入其中,还需要它是灵活的,return List<T>
包含数据已加载。
所以现在我的 JSONLoader
class 读作:
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;
}
}
和 ILoader:
public interface ILoader<T>{
void Read();
List<T> Load();
}
现在,当我回到 DataLoader
class 时,如您所见,我失去了调用 ILoader
的灵活性,因为我需要告诉正在使用通用 class。
我试图将它封装在另一个接口中,但是 DataLoader
中的 loader.Load()
调用被破坏了,因为它 return 是一个 List<T>
.
现在我觉得要修复一侧,我会破坏另一侧。我一直在尝试思考抽象 classes 和接口的良好组合以相应地隔离所有内容,但我在想象它如何适合时遇到了很大的麻烦(我对 C# 很陌生并且不我还没有头脑灵活地看到我应该做什么和封装)。
我将其用作学习 C# 的练习,并希望尽可能使用最佳编程实践。我想要一个健壮的代码,没有重复并且 classes 之间的依赖性最少。我也希望得到一个解释,而不仅仅是一个工作代码。谢谢!
I have some issues with the interfaces (it complains that it cannot
convert JSONLoader expression to type
ILoader)
那是因为 List<T>
不是协变的。如果你想让它工作,而不是公开 List<T>
,你可以公开一个 IEnumerable<T>
,它在 T
中是协变的,并且还使你的 Loader<T>
与 [=16] 是协变的=]:
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;
}
}
我认为这个问题的答案很简单,但是由于我一直在这个问题上苦思冥想,所以我可能无法看清全局。
我想加载多个文件(在本例中,JSON),所以我创建了一个 DataLoader
class 来处理这个问题。在这个 class 中,我正在创建一个 ILoaders
的列表,class 将迭代和加载它,以便将来如果我使用 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
class 并使其实现 ILoader
接口时,我注意到我必须将 ILoader
转换为通用接口:我将总是需要提供根 class T
,JSONLoader
将把数据放入其中,还需要它是灵活的,return List<T>
包含数据已加载。
所以现在我的 JSONLoader
class 读作:
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;
}
}
和 ILoader:
public interface ILoader<T>{
void Read();
List<T> Load();
}
现在,当我回到 DataLoader
class 时,如您所见,我失去了调用 ILoader
的灵活性,因为我需要告诉正在使用通用 class。
我试图将它封装在另一个接口中,但是 DataLoader
中的 loader.Load()
调用被破坏了,因为它 return 是一个 List<T>
.
现在我觉得要修复一侧,我会破坏另一侧。我一直在尝试思考抽象 classes 和接口的良好组合以相应地隔离所有内容,但我在想象它如何适合时遇到了很大的麻烦(我对 C# 很陌生并且不我还没有头脑灵活地看到我应该做什么和封装)。
我将其用作学习 C# 的练习,并希望尽可能使用最佳编程实践。我想要一个健壮的代码,没有重复并且 classes 之间的依赖性最少。我也希望得到一个解释,而不仅仅是一个工作代码。谢谢!
I have some issues with the interfaces (it complains that it cannot convert JSONLoader expression to type ILoader)
那是因为 List<T>
不是协变的。如果你想让它工作,而不是公开 List<T>
,你可以公开一个 IEnumerable<T>
,它在 T
中是协变的,并且还使你的 Loader<T>
与 [=16] 是协变的=]:
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;
}
}