我可以指定"或"关键字"where"泛型类型参数约束

本文关键字:quot where 泛型类型 参数约束 关键字 我可以 | 更新日期: 2023-09-27 18:03:01

我有一个函数来做打乱比较

    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必须是icomable,但是值类型T可以是icomable或者在接口

下面实现
    public interface ICompareAsHtml
    {
      // Compare current "this" object with "obj"
      // and persist the difference in html somewhere
      // return number of differences.
      int compareAsHtml(object obj);
    }

我如何更新where行使编译通过(不删除它,不使用其中一个接口)?

或者更好,你可以阅读下面我的代码来了解我的情况。我需要使用下面的函数来比较字符串的集合,这是IComparable;或者比较一个拥抱类的集合,比如Sales,它实现了icompareashhtml,但没有IComparable。(因为太多的属性使得这个类很难实现CompareTo函数-不能给出"一个"数字来表示两个实例之间的"方向"answers"距离")

    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;
    }

欢迎所有建议/反馈/评论!

我可以指定"或"关键字"where"泛型类型参数约束

这不是框架支持的。然而,这样做的需要意味着缺少一个IComparableICompareAsHtml都应该实现的公共接口,而您可以约束它。

这里的坏消息是IComparable是框架的一部分,这意味着你不能改变它来实现缺失的接口。好消息是IComparable已经相当简单了……也许就是那个缺失的接口。

ICompareAsHtml不是框架的一部分,并且我目前可以通过Google搜索的任何产品的文档中都没有提到,这意味着它可能是一个您可以更改的接口。如果这是真的,只要让ICompareAsHtml实现IComparable,只约束IComparable,你就会满足你的条件

您不能在约束列表上执行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
    }
}

最后,我想出了使用两个函数而不是一个

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为专有名称。但是有两个函数可以解决这个问题。

将旧函数更改为private,以避免外部直接访问。

你觉得这个解决方案怎么样?