2013-02-02 222 views
0

我的程序中有一個類SortableObservableCollection<T>,它繼承自ObservableCollection<T>。它有一個叫做Sort功能:聲明屬性是函數委託的正確方法是什麼

public void Sort<TKey>(Func<T, TKey> keySelector, int skip = 0) 
{ 
    // . . . 
} 

我要聲明一個名爲Func<T, TKey>類型的Key1財產。我已經嘗試過:

public Func<T, TKey> Key1<T, TKey> { get; set; } 

但是我得到左花括號的語法錯誤。該錯誤表示編譯器期待左括號。我試過把它作爲一個字段聲明:

public Func<T, TKey> Key1<T, TKey>; 

但是然後編譯器給我在分號上相同的消息。

聲明此屬性的正確語法是什麼?

+2

屬性不能像通用方法一樣泛型,請參閱[爲什麼C#不允許泛型屬性?](http://stackoverflow.com/questions/8620883/)。如果該屬性位於通用類的類(或結構或接口)內,則該屬性的類型當然可能取決於包含類的類型參數,但該屬性不能像通用方法那樣引入新的類型參數。 –

+0

@JeppeStigNielsen:謝謝。雖然我沒有閱讀所有內容,但是你提供的鏈接解釋了爲什麼我不能做我想做的事情。 –

回答

0

雖然每個人的答案會的工作,他們不正是我一直想把這個問題。我本來類的方法稱爲Sort:

public void Sort<TKey>(Func<T, TKey> keySelector, . . .) { 
    // . . . 
} 

這個工作很好,但後來我發現是有關調用排序方法不止一次在我的UI中的錯誤。排序本身起作用,那不是問題。這個錯誤很複雜,很難解釋,我寧願不去理解它。但最簡單的解決方案是確保集合只在正確的密鑰上排序一次。關鍵在於鍵的不同取決於集合綁定的特定下拉菜單。所以我需要一種方法來封裝收集中的排序標準,以便它能夠在唯一的時間進行正確的排序。

因爲我已經有了上述的Sort方法,所以我想最簡單的做法是將keySelector參數放入類的屬性中。事實證明,語言不會讓你這樣做,現在我知道並理解爲什麼。

我最終做了什麼來取代Func屬性,並且引用了一個實現了IComparer<T>的對象。我毫不費力地聲明這個屬性,並且很容易聲明一個類,它爲在集合聲明中作爲參數T傳遞的每個類型實現它。我只是初始化屬性分配的集合對象後,我改寫了Sort方法,所以它看起來是這樣的:

public void Sort() { 
    if (Comparer != null) { 
     InternalSort(Items.Skip(RowsToSkip).OrderBy(item => item, Comparer)); 
    } else { 
     InternalSort(Items.Skip(RowsToSkip).OrderBy(item => item)); 
    } 
} 

RowsToSkip是指定在收集開始有多少行對類的int財產被跳過。這使我可以在列表的開始處添加一個條目,如「選擇一個選項」,但不能將其移動。

3

首先,你需要擴大你的類定義爲包括TKey泛型參數,而不是僅僅讓它在Sort()方法級別:

public class SortableObservableCollection<T, TKey> 
{ 
} 

之後,你將不再需要第二一套通用的參數:

public Func<T, TKey> Key1 { get; set; } 

您也可以從Sort()方法去除泛型參數。

+0

當我嘗試這樣做時,我得到「無法找到類型或名稱空間名稱'TKey'(您是否缺少使用指令或程序集引用?」) –

+0

@Tony - 該聲明假定TKey是通用參數類。如果不是,您需要定義一些具體類型而不是泛型參數。 –

0

試試這個:

public class SortableObservableCollection<T, TKey>:ObservableCollection<T> 
{ 
    public Func<T,TKey> Key1 {get; set;} 
} 
1

您在這裏有2個選項。 首先,您可以將TKey作爲泛型參數添加到類中。

public class SortableObservableCollection<T, TKey> : ObservableCollection<T> 
{ 
    public void Sort(Func<T, TKey> keySelector, int skip = 0) 
    { 
     //... 
    } 
    public Func<T, TKey> Key1 { get; set; } 
} 

現在你的第二個選擇,如果你不能或不想爲類添加另一個泛型參數是爲了避免使用key1屬性在一起。

public class Sort2<T> : ObservableCollection<T> 
{ 
    Type keyType; 
    object key1; 

    public void Sort<TKey>(Func<T, TKey> selector, int skip = 0) 
    { 
     //... 
    } 

    public void SetKey<TKey>(TKey val) 
    { 
     keyType = typeof(TKey); 
     key1 = val; 
    } 
    public TKey GetKey<TKey>() 
    { 
     return (TKey)key1; 
    } 

    public Type GetKeyType() 
    { 
     return keyType; 
    } 

} 
3

您試圖創建一個通用屬性,但屬性不能是通用的。你必須以某種方式解決這個問題。我能想到的幾個選項:

  1. 聲明委託作爲object -returning:

    public Func<T, object> Key1 { get; set; } 
    
  2. 使屬性爲方法(或兩種方法,如果你還需要一個getter)。這裏的問題是,你需要委託存儲在非通用領域,這將是很難與後來的工作:

    private Delegate key1; 
    
    public void SetKey1<TKey>(Func<T, TKey> key1) 
    { 
        this.key1 = key1; 
    } 
    
  3. 如果排序鍵的類型不會改變,讓你的類的類型參數:

    public class SortableObservableCollection<T, TKey> 
    { 
        public Func<T, TKey> Key1 { get; set; } 
    
        … 
    } 
    
相關問題