实现IComparable<T>

6

当我尝试调整Jon Skeet的书“C# in depth”中第3.4节的示例代码时,出现以下错误信息:

类型“list_3_4.Dog”不能作为泛型类型或方法“list_3_4.Program.CompareToDefault(T)” 中类型参数“T”的使用。无法将“list_3_4.Dog”隐式转换为“System.IComparable”。

以下是我的代码...

using System;

namespace list_3_4
{
     class Program
     {
          static void Main(string[] args)
          {
               //string mystring;
               Dog d = new Dog("howie");

               Console.WriteLine(CompareToDefault("x"));
               Console.WriteLine(CompareToDefault(10));
               Console.WriteLine(CompareToDefault(0));
               Console.WriteLine(CompareToDefault(-10));              
               Console.WriteLine(CompareToDefault(DateTime.MinValue));

               Console.WriteLine(CompareToDefault(d));

               Console.ReadKey();
          }

          static int CompareToDefault<T> (T value) where T: IComparable<T>
          {
               return value.CompareTo(default(T));               
          }

     }

     public class Dog 
     {
          private string _name;

          public Dog(string name)
          {
               _name = name;
          }
         }
}

我如何像Jon Skeet的示例代码一样添加一个"Dog"引用类型? 我知道Dog需要实现IComparable,但我不知道怎么做!


1
你的 Dog 类似乎没有按照泛型约束 where T : IComparable<T> 指定的方式实现 IComparable<Dog> 接口。 - Adam Houldsworth
1
+1 对于一个我可以复制、粘贴并进行测试的代码示例。虽然一个问题也不错哈哈 - Adam Houldsworth
以下代码无法正常工作:public class Dog : IComparable<T>,我尝试了public class Dog: IComarable<Dog>...这个可以工作! - dannyrosalex
1
@DemetriusBerlioz 这对于引用类型来说是毫无意义的,因为它们始终会使用 default(T) 默认为 null,所以你可以直接测试是否为 nullif (d == null) - Adam Houldsworth
@AdamHouldsworth,谢谢你在这个问题上帮我解决! - dannyrosalex
2个回答

13

您需要定义方法并指定一个类型 T,该类型应为 IComparable<T>

where T: IComparable<T>

但是 Dog 没有实现 IComparable<Dog>

需要进行以下操作:

public class Dog : IComparable<Dog>
{
 //this will allow you to do a quick name comparison
 public string Name { get; set;}
 public int CompareTo(Dog other)
 {//compare dogs by name
        return this._name.CompareTo(other.Name);
 }
}

注意: 对于引用类型,default(T) 将返回null,因此您应该在某处进行空值检查。请阅读有关 msdn 上的默认值


2
@Demetrius 你最终决定的实现应该对 _nameotherother.Name 进行空值检查。 - Adam Houldsworth
你实际上不需要 Name 属性。如果你确实要添加它,至少也应该将 setter 设置为私有。 - Servy
@AdamHouldsworth 或者你可以直接使用静态的 string.Compare,它会为你进行空值检查。 - Servy
是的,我尝试了你指出的实现方式,但没有意识到"CompareTo"附加在哪里...只是对象本身...就像this.CompareTo(other)...这样是行不通的。正如Alex在上面指出的那样,它是针对属性的..._name.CompareTo(other._name)...如果没有属性会怎么样呢? - dannyrosalex
@Servy 好的。我记不清具体实现细节了,所以我不确定 other 是否也需要进行空值检查。为了清晰起见,我总是倾向于这样做,但我从来没有测试过,哈哈。 - Adam Houldsworth
大家好,我已经尝试给那些给出真诚答案和评论的人点赞,但是我有一种感觉,当我读完Skeet的书第四章“使用可空类型时不说话”后,我很快就会回答自己的问题。 - dannyrosalex

10

你的 Dog 类应该实现 IComparable<T> 接口。

 public class Dog: IComparable<Dog>
 {
      private string _name;

      public Dog(string name)
      {
           _name = name;
      }

      public int CompareTo( Dog other )
      {
           if (other == null)
               return 1;
           return string.Compare( _name, other._name );
      }
 }

公共类Dog:IComparable<T>不起作用,只有公共类Dog:IComparable<Dog>才能工作...某种程度上...现在我得到了一个NullReferenceException??? - dannyrosalex
@DemetriusBerlioz 我已经添加了一个检查 other == null 的语句,现在应该可以工作了。 - Alex

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接