2012-01-20 120 views
0

我已經在我的基類中定義了一個抽象方法以獲取泛型類型。我希望能夠做的是將我的一個子類的列表傳遞給這個抽象方法。我只是不確定如何在子類中正確處理這個問題?如何將泛型類型轉換爲列表

基類抽象方法:

protected abstract void Validate<T>(T records); 

子類實現(如果我有問題):

電話方法(轉至LogEventRecord的列表):

Validate<List<LogEventRecord>>(records); 

方法(想要處理LogEventRecord列表):

 protected override void Validate<T>(T records) 
     { 
      //How do I handle records here? I want them to be List<LogEventRecord> and when i debug 
      //They appear to be coming in that way, but I can't utilize them in the method 
      //How do I cast the records to List<LogEventRecord>? Is that what I do? 

     } 

任何建議將不勝感激。

回答

5

聲明的方法是這樣的:

protected abstract void Validate<T>(IEnumerable<T> records) 

,並調用它是這樣的:

Validate(records); 

編譯器應該能夠推斷泛型方法的類型,沒有必要將其列入明確。如果你真的想包括類型,或者類型推斷由於某種原因失敗(你就會知道這一點,因爲編譯器會抱怨),你可以這樣做:

Validate<LogEventRecord>(records); 

那麼你的實現可以使用記錄像這樣:

protected override void Validate<T>(IEnumerable<T> records) 
{ 
    //you can use a foreach loop 
    foreach (T record in records) 
    { 

    } 

    //Or "linq" operators: 
    bool isValid = records.Any(r => r.IsNotValid); 

    //Or linq query comprehension syntax: 
    bool isValid2 = (from r in records 
        where r.IsNotValid 
        select r).Any(); 

} 

但現在你知道T的唯一的事情是,它是一個對象。你不能用類型爲「object」的變量做很多事情,所以這還不是很有用。實際上,我樣本中的後兩個選項現在會失敗,因爲.IsNotValid屬性可能不存在。相反,你可能想要(也許已經有)一個接口來描述你將使用這個函數的對象:它們可能總是要麼是日誌,要麼是某些公共基類型的記錄。如果是這樣的話,你有兩個選擇。首先是限制你的泛型類型。你這樣做,通過改變你的方法簽名是這樣的:

protected abstract void Validate<T>(IEnumerable<T> records) where T : MyRecordInterface 

另一種選擇是,在C#4上有接口(包括IEnumerabe < T>,將讓你避免了需要變化的新支持。這裏所有的通用方法,要充分利用這一點,只是確保你在Visual Studio 2010中使用.NET 4.0或更高版本,並宣佈這樣的方法:

protected abstract void Validate(IEnumerable<MyRecordInterface> records) 

你需要.NET 4中,而不是隻是針對早期版本的框架的c#4,因爲您需要IEnumerable的.Net 4版本。它的建立包含了對差異的必要支持。

最後,還有第三個選項。你可以一個delegate參數添加到您的方法,每個項目在列表轉換爲一個布爾值,像這樣:

protected abstract void Validate<T>(IEnumerable<T> records, Func<T, bool> isValid) 

protected override void Validate<T>(IEnumerable<T> records, Func<T, bool> isValid) 
{ 
    bool recordsAreValid = records.Any(r => !isValid(r)); 
} 

Validate(records, l => ((LogEventRecord)l).IsValid); 
6

聽起來真的你的方法有錯誤的簽名。參數名稱爲複數的事實,但它只是接受T意味着。我懷疑它應該是:

protected abstract void Validate<T>(IEnumerable<T> records); 

然後在你的實現中,你可以簡單地遍歷記錄。話雖如此,如果你的子類只能驗證的LogEventRecord收集它很可能是你真的應該使類,而不是方法的一部分的類型參數部分:

public class Foo<T> 
{ 
    protected abstract void Validate(IEnumerable<T> records); 
} 

那麼你的子類會成爲:

public class Bar : Foo<LogRecord> 
{ 
    protected override void Validate(IEnumerable<LogRecord> records) 
    { 
     foreach (LogRecord record in records) 
     { 
      ... 
     } 
    } 
} 

儘管沒有更多的上下文,但很難知道這是否合適。如果它立即適合而不是,則可能需要更多地分類。

1

明確使用列表通常對我更好。

protected override void Validate<T>(List<T> records) 

稱它爲無類型參數,編譯器會看着辦吧:Validate(records)

+0

的IList 幾乎總是preferrable列出,和IEnumerable 幾乎總是preferrable到IList中。 –