我的程序中有一个名为SortableObservableCollection<T>
的类,它继承自ObservableCollection<T>
。它有一个名为Sort
的函数:
public void Sort<TKey>( Func<T, TKey> keySelector, int skip = 0 )
{
// . . .
}
我想声明一个名为Key1
的{{1}}类型的属性。我试过了:
Func<T, TKey>
但是我在左大括号上遇到语法错误。该错误表明编译器期望左括号。我试过把它变成一个字段声明:
public Func<T, TKey> Key1<T, TKey> { get; set; }
但是编译器在分号上给了我相同的信息。
声明此属性的正确语法是什么?
答案 0 :(得分:3)
首先,您需要扩展类定义以包含TKey
的通用参数,而不是仅仅使用Sort()
方法级别:
public class SortableObservableCollection<T, TKey>
{
}
之后,您将不需要第二组通用参数:
public Func<T, TKey> Key1 { get; set; }
您还可以从Sort()
方法中删除通用参数。
答案 1 :(得分:3)
您正在尝试创建一个通用属性,但属性不能是通用的。你必须以某种方式解决这个问题。我可以想到几个选择:
将委托声明为object
- 返回:
public Func<T, object> Key1 { get; set; }
将属性设置为方法(或两个方法,如果您还需要getter)。这样做的问题是你需要将委托存储在非泛型字段中,之后很难处理它:
private Delegate key1;
public void SetKey1<TKey>(Func<T, TKey> key1)
{
this.key1 = key1;
}
如果排序键的类型不会更改,请将其设为类的类型参数:
public class SortableObservableCollection<T, TKey>
{
public Func<T, TKey> Key1 { get; set; }
…
}
答案 2 :(得分: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 :(得分:0)
试试这个:
public class SortableObservableCollection<T, TKey>:ObservableCollection<T>
{
public Func<T,TKey> Key1 {get; set;}
}
答案 4 :(得分: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
属性,用于指定要跳过集合开头的行数。这让我可以在列表的开头添加“选择一个选项”这样的条目,而不是让它移动它。