0

我的程序中有一个类,SortableObservableCollection<T>它继承自ObservableCollection<T>. 它有一个名为Sort

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

我想声明一个名为Key1type的属性Func<T, TKey>。我试过了:

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

但是我在左大括号上遇到语法错误。该错误表明编译器需要一个左括号。我试过让它成为一个字段声明:

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

但是编译器在分号上给了我同样的信息。

声明此属性的正确语法是什么?

4

5 回答 5

3

首先,您需要扩展类定义以包含泛型参数,TKey而不仅仅是在Sort()方法级别:

public class SortableObservableCollection<T, TKey>
{
}

之后,您将不再需要第二组泛型参数:

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

您还可以从Sort()方法中删除泛型参数。

于 2013-02-02T17:57:55.673 回答
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; }
    
        …
    }
    
于 2013-02-02T18:25:43.897 回答
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;
    }

}
于 2013-02-02T18:16:43.983 回答
0

试试这个:

public class SortableObservableCollection<T, TKey>:ObservableCollection<T>
{
    public Func<T,TKey> Key1 {get; set;}
}
于 2013-02-02T18:01:35.283 回答
0

虽然每个人的答案都会奏效,但它们并不完全是我试图解决的问题。最初,我有一个名为的类的方法Sort:

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

这很好用,但后来我在我的 UI 中发现了一个与多次调用 Sort 方法有关的错误。排序本身有效,这不是问题。该错误令人费解且难以解释,我宁愿不深入探讨。但最简单的解决方案是确保集合仅在正确的键上排序一次。问题是键会根据集合绑定到的特定下拉列表而有所不同。所以我需要一种方法来封装集合中的排序标准,这样它就可以第一次也是唯一一次进行正确的排序。

由于我已经有了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属性,它指定要跳过集合开头的行数。这让我可以在列表的开头添加一个类似“选择一个选项”的条目,而不是让排序移动它。

于 2013-02-05T15:28:04.567 回答