111,093
社区成员




namespace System
{
/// <summary>
/// 定义一种特定于类型的通用比较方法,值类型或类通过实现此方法对其实例进行排序。
/// </summary>
/// <filterpriority>1</filterpriority>
[ComVisible(true)]
public interface IComparable
{
/// <summary>
/// 将当前实例与同一类型的另一个对象进行比较,并返回一个整数,该整数指示当前实例在排序顺序中的位置是位于另一个对象之前、之后还是与其位置相同。
/// </summary>
///
/// <returns>
/// 一个值,指示要比较的对象的相对顺序。 返回值的含义如下: 值 含义 小于零 此实例按排序顺序在 <paramref name="obj"/> 前面。 零 此实例与 <paramref name="obj"/> 在排序顺序中出现的位置相同。 大于零 此实例按排序顺序在 <paramref name="obj"/> 后面。
/// </returns>
/// <param name="obj">与此实例进行比较的对象。</param><exception cref="T:System.ArgumentException"><paramref name="obj"/> 不具有与此实例相同的类型。</exception><filterpriority>2</filterpriority>
int CompareTo(object obj);
}
确实是装箱了.[/quote]
咦 我使用了IComparable<int> 怎么还是false呢? 不过感觉应该还是IComparable的问题 待我再去看看底层实现.[/quote]
/// <summary>
/// 将此实例与指定对象进行比较并返回一个对二者的相对值的指示。
/// </summary>
///
/// <returns>
/// 一个有符号数字,指示此实例和 <paramref name="value"/> 的相对值。 返回值 说明 小于零 此实例小于 <paramref name="value"/>。 零 此实例等于 <paramref name="value"/>。 大于零 此实例大于 <paramref name="value"/>。 - 或 - <paramref name="value"/> 为 null。
/// </returns>
/// <param name="value">要比较的对象,或为 null。</param><exception cref="T:System.ArgumentException"><paramref name="value"/> 不是 <see cref="T:System.Int32"/>。</exception><filterpriority>2</filterpriority>
public int CompareTo(object value);
/// <summary>
/// 将此实例与指定的 32 位有符号整数进行比较并返回对其相对值的指示。
/// </summary>
///
/// <returns>
/// 一个有符号数字,指示此实例和 <paramref name="value"/> 的相对值。 返回值 说明 小于零 此实例小于 <paramref name="value"/>。 零 此实例等于 <paramref name="value"/>。 大于零 此实例大于 <paramref name="value"/>。
/// </returns>
/// <param name="value">要比较的整数。</param><filterpriority>2</filterpriority>
[TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
public int CompareTo(int value);
貌似还是装箱了啊,namespace System
{
/// <summary>
/// 定义一种特定于类型的通用比较方法,值类型或类通过实现此方法对其实例进行排序。
/// </summary>
/// <filterpriority>1</filterpriority>
[ComVisible(true)]
public interface IComparable
{
/// <summary>
/// 将当前实例与同一类型的另一个对象进行比较,并返回一个整数,该整数指示当前实例在排序顺序中的位置是位于另一个对象之前、之后还是与其位置相同。
/// </summary>
///
/// <returns>
/// 一个值,指示要比较的对象的相对顺序。 返回值的含义如下: 值 含义 小于零 此实例按排序顺序在 <paramref name="obj"/> 前面。 零 此实例与 <paramref name="obj"/> 在排序顺序中出现的位置相同。 大于零 此实例按排序顺序在 <paramref name="obj"/> 后面。
/// </returns>
/// <param name="obj">与此实例进行比较的对象。</param><exception cref="T:System.ArgumentException"><paramref name="obj"/> 不具有与此实例相同的类型。</exception><filterpriority>2</filterpriority>
int CompareTo(object obj);
}
确实是装箱了.[/quote]
咦 我使用了IComparable<int> 怎么还是false呢? 不过感觉应该还是IComparable的问题 待我再去看看底层实现.namespace System
{
/// <summary>
/// 定义一种特定于类型的通用比较方法,值类型或类通过实现此方法对其实例进行排序。
/// </summary>
/// <filterpriority>1</filterpriority>
[ComVisible(true)]
public interface IComparable
{
/// <summary>
/// 将当前实例与同一类型的另一个对象进行比较,并返回一个整数,该整数指示当前实例在排序顺序中的位置是位于另一个对象之前、之后还是与其位置相同。
/// </summary>
///
/// <returns>
/// 一个值,指示要比较的对象的相对顺序。 返回值的含义如下: 值 含义 小于零 此实例按排序顺序在 <paramref name="obj"/> 前面。 零 此实例与 <paramref name="obj"/> 在排序顺序中出现的位置相同。 大于零 此实例按排序顺序在 <paramref name="obj"/> 后面。
/// </returns>
/// <param name="obj">与此实例进行比较的对象。</param><exception cref="T:System.ArgumentException"><paramref name="obj"/> 不具有与此实例相同的类型。</exception><filterpriority>2</filterpriority>
int CompareTo(object obj);
}
确实是装箱了.[/quote]
你们没有理解我的意思
我是说,这样做没有意义。namespace System
{
/// <summary>
/// 定义一种特定于类型的通用比较方法,值类型或类通过实现此方法对其实例进行排序。
/// </summary>
/// <filterpriority>1</filterpriority>
[ComVisible(true)]
public interface IComparable
{
/// <summary>
/// 将当前实例与同一类型的另一个对象进行比较,并返回一个整数,该整数指示当前实例在排序顺序中的位置是位于另一个对象之前、之后还是与其位置相同。
/// </summary>
///
/// <returns>
/// 一个值,指示要比较的对象的相对顺序。 返回值的含义如下: 值 含义 小于零 此实例按排序顺序在 <paramref name="obj"/> 前面。 零 此实例与 <paramref name="obj"/> 在排序顺序中出现的位置相同。 大于零 此实例按排序顺序在 <paramref name="obj"/> 后面。
/// </returns>
/// <param name="obj">与此实例进行比较的对象。</param><exception cref="T:System.ArgumentException"><paramref name="obj"/> 不具有与此实例相同的类型。</exception><filterpriority>2</filterpriority>
int CompareTo(object obj);
}
确实是装箱了.using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class SomeClass<T, U>
where T : class
where U : struct, T
{
public void foo(T a, T b)
{
Console.WriteLine(a == b);
}
}
class Program
{
static void Main(string[] args)
{
SomeClass<IFormattable, int> x = new SomeClass<IFormattable, int>();
x.foo(1, 1);
}
}
}
不过你的理论有点问题
这样的代码还是可以编译的。 IComparable<int> i1 = 3;
IComparable<int> i2 = 3;
Console.WriteLine(i1 == i2);
输出false
可以说,这是一段莫名其妙的代码,因为IComparable的比较方式的调用方法不是== 而是CompareTo
比如 Console.WriteLine(3.CompareTo(3));
以下是个人推测,未100%验证.
我们平常使用的== 是int类型重载了继承自object的==方法 所以3==3返回ture
而IComparable<int>的实例,没有去重载==,所以a==b,其实是调用的IComparable<int>的实例从object继承过来的方法,一个侧面可以证实此点的方法,诸位可以试试IComparable<string>,这次就会返回true了.
楼主这个问题也许没有实际意义,但确实让我加深了不少对c#底层的理解,非常感谢.
关于这个问题,可以引申出很多有意思的地方,我觉得我干脆写一篇博客算了.
namespace System
{
/// <summary>
/// 定义一种特定于类型的通用比较方法,值类型或类通过实现此方法对其实例进行排序。
/// </summary>
/// <filterpriority>1</filterpriority>
[ComVisible(true)]
public interface IComparable
{
/// <summary>
/// 将当前实例与同一类型的另一个对象进行比较,并返回一个整数,该整数指示当前实例在排序顺序中的位置是位于另一个对象之前、之后还是与其位置相同。
/// </summary>
///
/// <returns>
/// 一个值,指示要比较的对象的相对顺序。 返回值的含义如下: 值 含义 小于零 此实例按排序顺序在 <paramref name="obj"/> 前面。 零 此实例与 <paramref name="obj"/> 在排序顺序中出现的位置相同。 大于零 此实例按排序顺序在 <paramref name="obj"/> 后面。
/// </returns>
/// <param name="obj">与此实例进行比较的对象。</param><exception cref="T:System.ArgumentException"><paramref name="obj"/> 不具有与此实例相同的类型。</exception><filterpriority>2</filterpriority>
int CompareTo(object obj);
}
确实是装箱了.[/quote]
你们没有理解我的意思
我是说,这样做没有意义。[/quote]
这里的没有意义应该是:本来传入一个值类型,最终输出的结果却跟我们的预期是偏差的,但是这种偏差本身是可以解释的:装箱了之后,引用肯定不一样,说到底,只能传入引用进行比较才有意义,不过引用的比较确实没有必要搞这么一套。
但是在语言层面,我觉得还是有一点意义的。特别是对于像我这种刚接触C#的人来说:1)约束 引用和值约束,讨论的只是一个可否为null。对于引用,比较的就是引用,一个地址,类型相同可以比较,但是值类型呢?基于泛型,就没法比较,极端的例子,两个浮点数进行==元算就是不合理的,编译器直接不买账(这样理解是否可行?) 2 装箱是个从有到有的过程,其实就是开辟空间进行转存,但是拆箱是一个从有到可能有的过程,需要提供正确的类型,否则拆出来的东西也没法用,所以,如果约束为引用的话,值类型的传入是没有问题的,反正比较的是引用,这就好比,本来想比较下两同学的成绩的,但是编译器只看学号的大小了,学号可以理解为对同学的引用。 3 值类型本身也实现了接口,另外值类型都有一个默认的无参构造函数,这个就是可以实现 where T:class where U: struct, T这种约束的原因。 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class SomeClass<T, U>
where T : class
where U : struct, T
{
public void foo(T a, T b)
{
Console.WriteLine(a == b);
}
}
class Program
{
static void Main(string[] args)
{
SomeClass<IComparable, int> x = new SomeClass<IComparable, int>();
x.foo(1, 1);
}
}
}