如何在c#中存储返回的List <t>?

时间:2017-06-16 10:47:46

标签: c# generics

这应该很简单,但我一直遇到问题。我有一个泛型类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存储在调用类中?如何声明可以容纳任何类型的字段或属性?

3 个答案:

答案 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

然后通过返回来切换案例。