我有一个做加扰比较的功能
public static int ScrambledEquals<TKey, T>(
IDictionary<TKey, T> list1,
IDictionary<TKey, T> list2)
where TKey : IComparable
where T : ICompareAsHtml or IComparable // compilation failure on this line
{
// ...
}
public static int ScrambledEquals<TKey, T>(
IDictionary<TKey, T> list1,
IDictionary<TKey, T> list2)
where TKey : IComparable
where T : ICompareAsHtml {} // This works!
TKey必须是IComparable,但值类型T可以是IComparable或在接口下面实现
public interface ICompareAsHtml
{
// Compare current "this" object with "obj"
// and persist the difference in html somewhere
// return number of differences.
int compareAsHtml(object obj);
}
如何更新要编译的行传递的位置(不删除它,不使用其中一个接口)?
或者更好的是,您可以阅读下面的代码来了解我的情况。我需要使用下面的函数来比较一个字符串的集合,这是IComparable;或比较一个拥抱类的集合,比如Sales,它实现了ICompareAsHtml而不是IComparable。 (因为太多的属性使得这个类很难实现CompareTo函数 - 不能给出“一个”数字来表示两个实例之间的“方向”和“距离”。)
public static int ScrambledEquals<TKey, T>(
IDictionary<TKey, T> list1,
IDictionary<TKey, T> list2)
where TKey : IComparable
// where T : ICompareAsHtml or IComparable
// commented out above line to make compilation pass
{
int nDIff = 0;
List<TKey> bothKeys = list1.Keys.Union<TKey>(list2.Keys).ToList();
bothKeys.Sort();
foreach (TKey key in bothKeys)
{
// code omitted - not related to this question
{
// key exist in both lists.
object o1 = list1[key];
object o2 = list2[key];
if (o1 is IComparable && o2 is IComparable)
{
IComparable v1 = (IComparable)o1;
IComparable v2 = (IComparable)o2;
if (0 != v1.CompareTo(v2))
{
nDIff++;
// Save the difference in html
}
}
else if (o1 is ICompareAsHtml && o2 is ICompareAsHtml)
{
ICompareAsHtml v1 = (ICompareAsHtml)o1;
ICompareAsHtml v2 = (ICompareAsHtml)o2;
// Save the difference
nDIff += v1.compareAsHtml(v2);
}
else
{
// If I can use where keyword
// I don't need this exception
throw new Exception(@"Error: Program error
- Value Type is neither IComparable nor ICompareAsHtml.");
}
}
}
}
return nDIff;
}
欢迎所有建议/反馈/意见!
答案 0 :(得分:3)
这是不框架支持的东西。但是,执行此操作的需要意味着缺少IComparable
和ICompareAsHtml
应该实现的公共接口,而是可以约束。
这里的坏消息是IComparable
是框架的一部分,这意味着你无法改变它来实现那个缺失的界面。好消息是IComparable
已经非常简单了......也许它可以 缺少界面。
ICompareAsHtml
不是该框架的一部分,我目前无法通过Google搜索任何产品的文档中未提及,这意味着它可能是您可以更改的界面。如果这是真的,只需让ICompareAsHtml
实施IComparable
并限制为IComparable
,就可以满足您的条件
答案 1 :(得分:1)
您无法在约束列表中执行OR,请查看此处的文档: https://msdn.microsoft.com/en-us/library/d5x73970.aspx
也许你能做的就是让你的界面来自IComparable:
public interface ICompareAsHtml : IComparable
{
int compareAsHtml(object obj);
}
class CompareAsHtml : ICompareAsHtml
{
public int CompareTo(object obj)
{
return compareAsHtml(obj);
}
public int compareAsHtml(object obj)
{
//do the core comparison here and return
}
}
答案 2 :(得分:0)
最后,我想出使用两个函数而不是一个
public static int ScrambledEqualsComparable<TKey, T>(
IDictionary<TKey, T> list1,
IDictionary<TKey, T> list2)
where TKey : IComparable
where T : IComparable
{
return ScrambledEquals(list1, list2);
}
public static int ScrambledEqualsCompareAsHtml<TKey, T>(
IDictionary<TKey, T> list1,
IDictionary<TKey, T> list2)
where TKey : IComparable
where T : ICompareAsHtml
{
return ScrambledEquals(list1, list2);
}
private static int ScrambledEquals<TKey, T>(
Dictionary<TKey, T> list1,
Dictionary<TKey, T> list2)
where TKey : IComparable
{
// the same as above code - No need to throw exception as
// it has to be one of ICompareAsHtml or IComparable.
}
当然,我可以将ScrambledEqualsCompareAsHtml,ScrambledEqualsComparable重命名为专有名称。但是两个功能可以解决这个问题。当然旧功能改为私有,以避免从外部直接访问。
你觉得这个解决方案怎么样?