这应该很简单,但我一直遇到问题。我有一个泛型类Csvs<T>
,其方法通过名为List<T>
的属性返回类型Dockets
。 (该方法读取CSV文件并返回该CSV文件中的记录列表.T是该CSV文件的类型,该文件在一系列模型中定义,其中包含标题行作为属性)
在我的调用类中(我不能制作泛型),我有一个基于enum
的switch语句,它包含我在T中使用的类的名称。
switch (_userInput.CsvType)
{
case CsvType.Type1:
var csvType1 = new Csvs<Type1>(_userInput);
_dockets = csvType1.Dockets;
break;
case CsvType.Type2:
var csvType2 = new Csvs<Type2>(_userInput);
_dockets = csvType2.Dockets;
break;
case CsvType.Type3:
var csvType3 = new Csvs<Type3>(_userInput);
_dockets = csvType3.Dockets;
break;
// more cases here [...]
default:
throw new ArgumentOutOfRangeException();
}
(如果我能找到比使用此开关更好的方法,那将会很好,但它现在可以使用。)
什么不起作用,或者我不知道该怎么做,是如何声明_dockets
?因为T可以是任何类型。我已经尝试提取接口ICsvs
并让类继承它,然后声明
var _dockets = new List<ICsvs>;
但这会引发错误,我无法将List<Type1>
隐式转换为List<ICsvs>
。
我无法将列表转换为类型List<ICsvs>
。 (然后我得到下一个例外)
无法通过引用转换,装箱转换,拆箱转换,换行转换或空类型转换将类型'System.Collections.Generic.List'转换为'System.Collections.Generic.List'
如果我使用抽象类,也会发生同样的情况。
那么,如何将返回的List存储在调用类中?如何声明可以容纳任何类型的字段或属性?
答案 0 :(得分:1)
实现这一目标的最简单方法是使所有类型实现ICsv,如下所示:
interface ICsv { }
class CsvType1 : ICsv { }
class CsvType2 : ICsv { }
class Csvs<TCsvModel>
where TCsvModel: ICsv
{
public Csvs(IList<TCsvModel> csvModel)
{
this.Dockets = csvModel;
}
public IList<TCsvModel> Dockets { get; private set;}
}
所以你可以这样使用:
IEnumerable<ICvs> dockets;
var cvsType1 = new Csvs<CsvType1>(_input);
dockets = cvsType1.Dockets
var cvsType2 = new Csvs<CsvType2>(_input);
dockets = cvsType2.Dockets
答案 1 :(得分:0)
你可以做的最有意义/多态的事情是让Dockets
属性返回一个描述你用它们做什么的接口。根据您的要求,可能会或可能不会 - 但您没有其他选择。正如我评论的那样,Generics在编译时知道类型时才真正有效。
举个例子。界面
public interface IDockets
{
void DoSomethingWithRecords();
}
将从您的Csvs
类
public class Dockets<T> : IDockets
{
private IEnumerable<T> dockets;
public Dockets(IEnumerable<T> dockets)
{
this.dockets = dockets;
}
public void DoSomethingWithRecords()
{
foreach(var docket in dockets)
Console.WriteLine(docket); // do whatever
}
}
此课程将从您的Csvs
班级Dockets
属性
public class Csvs<T>
{
private List<T> parsedDockets; // assume you have something like this:
public IDockets Dockets{ get { return new Dockets(parsedDockets); } }
}
您的主叫代码
IDockets dockets = null;
switch (_userInput.CsvType)
{
case CsvType.Type1:
var csvType1 = new Csvs<Type1>(_userInput);
dockets = csvType1.Dockets;
break;
// Snip //
}
dockets.DoSomethingWithRecords();
答案 2 :(得分:0)
我认为对于我所追求的,即存储返回值以供以后使用,var window: UIWindow?
lazy var coreDataStack = CoreDataStack()
func getSavePathsForListWithName(_ name: String) -> String {
let pathsArray = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true)
let documentDirectory = pathsArray[0]
return documentDirectory.stringByAppendingPathComponent(name)}// Getting error in this line
是最佳答案(谢谢@Rahul)。我以后可以担心这种类型。谢谢大家的帮助。
dynamic
然后通过返回来切换案例。