2017-06-16 57 views
2

這應該很簡單,但我一直遇到這個問題。我有一個通用類Csvs<T>,通過名爲Dockets的屬性返回List<T>類型的方法。 (該方法讀取CSV文件並返回該CSV文件中記錄的列表,T是該CSV文件的類型,該文件在一系列模型中定義,其中包含標題行作爲屬性)如何在c#中存儲返回的列表<T>?

在我的調用類(我不能使通用),我有一個包含我在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(); 
      } 

(這將是很好,如果我能找到一個基於一個enum switch語句比使用這個開關更好的方法,但它現在可行。)

什麼不起作用,或者我不知道該怎麼辦,如何申報_dockets?由於T可以是任何類型。我試着提取接口ICsvs,並有類繼承它,然後聲明

var _dockets = new List<ICsvs>; 

但是,這將引發一個錯誤,我不能隱式轉換的List<Type1>List<ICsvs>

而且我不能將該列表投射到類型List<ICsvs>。 (然後我得到了一個異常)

無法通過引用轉換型「System.Collections.Generic.List」轉換爲「System.Collections.Generic.List」,裝箱轉換,取消裝箱轉換,包裝轉換,或空類型轉換

如果我使用抽象類,則會發生同樣的情況。

那麼,如何將返回的List存儲在調用類中?我如何聲明可以容納任何類型的字段或屬性?

+0

當您在編譯時知道類型時,泛型始終工作得最好。如果你只知道他們在運行時鍵入,你可能*不想要泛型。 – Jamiec

+0

@Jamiec,通用類的作品...我只是不知道如何存儲返回類型? – ToshiBoy

+1

正是我的觀點。您可以使用開關來實例化正確的泛型類,但不能以任何有意義的方式使用它,因爲您不知道它們的類型。 – Jamiec

回答

0

我認爲我以後的事情,即存儲以後使用的返回值,dynamic是最好的答案(謝謝@Rahul)。我可以在後面擔心類型。感謝大家的幫助。

dynamic _dockets; 

然後通過返回切換大小寫。

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 
+0

很好。謝謝。 – ToshiBoy

+0

這與OP代碼無效的原因不一樣。 http://rextester.com/PRWX41261 – Jamiec

+0

不,關閉:它拋出'參數1:無法從'System.Collections.Generic.List '轉換爲'System.Collections.Generic.IEnumerable '' – ToshiBoy

0

最有意義/多態性的事情你可以做的就是讓Dockets屬性返回一個描述你對它們做什麼的接口。根據您的要求,這可能也可能不可行 - 但您沒有其他選擇。正如我所評論的,當您在編譯時知道類型時,泛型真的只會運行良好。

作爲一個例子。接口

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 
    } 
} 

返回這個類,然後從你的CsvsDockets財產

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(); 
+0

IEnumerable的問題是我需要添加CSV中的值,所以List會更好。 – ToshiBoy

+0

@ToshiBoy無論列表還是枚舉都沒有區別。無論如何,你大概會把它們加到'Csvs'的列表中 - 當你將它們吐出到'Dockets'時,你可能不需要再添加任何東西。 – Jamiec

相關問題