我有以下代码
public class SortTerm<T>
{
public System.Func<T, System.IComparable> Sort;
public SortDirection Direction;
public SortTerm(System.Func<T, System.IComparable> sorter, SortDirection direction)
{
this.Sort = sorter;
this.Direction = direction;
}
public SortTerm(System.Func<T, System.IComparable> sorter)
: this(sorter, SortDirection.Ascending)
{ }
public static SortTerm<T> Create<TKey>(System.Func<T, TKey> sorter, SortDirection direction)
where TKey : System.IComparable
{
return new SortTerm<T>((System.Func<T, System.IComparable>)(object)sorter, direction);
} // End Constructor
public static SortTerm<T> Create<TKey>(System.Func<T, TKey> sorter)
where TKey : System.IComparable
{
return Create<TKey>(sorter, SortDirection.Ascending);
} // End Constructor
}
需要将System.Func<T, TKey>
转换为System.Func<T, IComparable>
为什么
SortTerm<Db.T_projects>.Create(x => x.name);
工作,而
SortTerm<Db.T_projects>.Create(x => x.id);
提供无效演员
InvalidCastException:无法转换类型为&#39; System.Func2 [Db.T_projects,System.Int64]&#39;输入 &#39; System.Func2 [Db.T_projects,System.IComparable]&#39;
当long / Int64定义为
时public struct Int64 : IComparable, IComparable<Int64>, IConvertible, IEquatable<Int64>, IFormattable
虽然字符串定义与IComparable没有区别......
public sealed class String : IEnumerable<char>, IEnumerable, IComparable, IComparable<String>, IConvertible, IEquatable<String>, ICloneable
完整性
public partial class T_projects
{
public long id; // int not null
public string name; // nvarchar(4000) not null
}
这不应该吗?
更重要的是,如何使这项工作?
注意:
会有一个List<SortTerm<T>>,
所以我不能在排序定义中使用TKey。
答案 0 :(得分:0)
正如RenéVogt在评论中告诉你的那样,这是因为值类型(如Int64)不支持共变量转换,而它适用于引用类型(例如字符串)。
通过将分拣机放入具有匹配签名的委托中来修复它 一个类型转换代表,所以说:
public class SortTerm<T>
{
public System.Func<T, System.IComparable> Sort;
public SortDirection Direction;
public SortTerm(System.Func<T, System.IComparable> sorter, SortDirection direction)
{
this.Sort = sorter;
this.Direction = direction;
}
public SortTerm(System.Func<T, System.IComparable> sorter)
: this(sorter, SortDirection.Ascending)
{ }
public static SortTerm<T> Create<TKey>(System.Func<T, TKey> sorter, SortDirection direction)
where TKey : System.IComparable
{
// return new SortTerm<T>((System.Func<T, System.IComparable>)(object)sorter, direction);
return new SortTerm<T>(delegate (T x) {
TKey ret = sorter(x);
return (System.IComparable)ret;
}, direction);
} // End Constructor
public static SortTerm<T> Create<TKey>(System.Func<T, TKey> sorter)
where TKey : System.IComparable
{
return Create<TKey>(sorter, SortDirection.Ascending);
} // End Constructor
}
您可能希望放弃where TKey : System.IComparable
限制,因为这不适用于可空类型,例如。
SortTerm<Db.T_projects>.Create(x => x.created);
的
public partial class T_projects
{
public long id; // int not null
public string name; // nvarchar(4000) not null
public System.DateTime? created; // datetime null
}
作为AFAIK,没有办法
where TKey : System.IComparable or System.Nullable<System.IComparable>
答案 1 :(得分:0)
docs反转方差仅适用于参考类型 - 例如string
。
差异仅适用于参考类型;如果指定值类型 对于变量类型参数,该类型参数对于该变量是不变的 结果构造类型。
所以你可以做到以下几点:
Func<string> myFunc = ...
Func<object> func = myFunc;
但不是这样:
Func<int> myFunc = ...
Func<object> func = myFunc;
要规避这一点,请将id
添加到object
:
Func<object> = () => (object) id;
您的代码中将包含以下内容:
SortTerm<Db.T_projects>.Create(x => (object) x.id);
或在现有代表上创建新代理:
Func<object> = () => myFunc();
在您的代码中对应于此:
SortTerm<Db.T_projects>.Create(new Func<MyType, object>(x => x.id));