根据MSDN中==运营商的文档,
对于预定义的值类型,如果操作数的值相等,则相等运算符(==)返回true,否则返回false.对于除string之外的引用类型,如果其两个操作数引用同一对象,则==返回true.对于字符串类型,==比较字符串的值.用户定义的值类型可以重载==运算符(请参阅运算符).用户定义的引用类型也是如此,尽管 默认情况下==的行为与上述预定义和用户定义的引用类型相同.
那么为什么这段代码片段无法编译呢?
bool Compare<T>(T x, T y) { return x == y; }
Run Code Online (Sandbox Code Playgroud)
我得到错误运算符'=='不能应用于'T'和'T'类型的操作数.我想知道为什么,因为据我所知,==运算符是针对所有类型预定义的?
编辑:谢谢大家.起初我没有注意到该声明仅涉及引用类型.我还认为为所有值类型提供了逐位比较,我现在知道这是不正确的.
但是,如果我使用引用类型,==操作符是否会使用预定义的引用比较,或者如果类型定义了一个,它是否会使用运算符的重载版本?
编辑2:通过反复试验,我们了解到==操作员在使用不受限制的泛型类型时将使用预定义的参考比较.实际上,编译器将使用它可以为限制类型参数找到的最佳方法,但不会再看了.例如,true即使Test.test<B>(new B(), new B())被调用,下面的代码也会始终打印:
class A { public static bool operator==(A x, A y) { return true; } }
class B : A { public static bool operator==(B x, B y) { return false; } }
class Test { void test<T>(T a, T …Run Code Online (Sandbox Code Playgroud) 以下内容无法编译:
public void MyMethod<T>(T value)
{
if (value == default(T))
{
// do stuff
}
}
Run Code Online (Sandbox Code Playgroud)
错误: Operator '==' cannot be applied to operands of type 'T' and 'T'
我不能使用value == null因为T可能是一个结构.
我不能用value.Equals(default(T))因为value可能null.
测试相等于默认值的正确方法是什么?
void Get<T>(Action<T> createObject)
{
T obj = createObject();
if(obj == default(T))
return obj;
// .. do a bunch of stuff
return obj;
}
Run Code Online (Sandbox Code Playgroud)
编译器错误:运算符'=='不能应用于'T'和'T'类型的操作数
我该怎么做呢?
我有一个结构(为了这个问题的目的)几乎模仿内置Point类型.
我需要在使用之前检查它是否已经实例化.什么时候Point,我可以这样做:
if (this.p == null)
Run Code Online (Sandbox Code Playgroud)
但现在生成以下错误:
运算符'=='不能应用于'ProportionPoint'和'<null>类型的操作数
如何将我的结构与null进行比较?还有另一种检查实例化的方法吗?
问题的第1部分:在下面的代码中,为什么value == default编译良好,而其他替代方法却没有?
bool MyEqual<T>(T value)
{
T value2 = default;
if (value == value2) // Error: Operator '==' cannot be applied to operands of type 'T' and 'T'
return true;
if (value == default(T)) // Error: Operator '==' cannot be applied to operands of type 'T' and 'T'
return true;
if (value == default) // No error
return true;
return false;
}
Run Code Online (Sandbox Code Playgroud)
问题的第2部分:在下面的代码中,为什么前三幅显示而后三幅false显示true?
bool MyEqual<T>(T value)
{
if (value == default)
return true; …Run Code Online (Sandbox Code Playgroud) 我希望能够检查值是否是其值类型的默认值.理想情况下,我想说:
DoSomething<TValue>(TValue value) {
if (value == default(TValue)) {
...
}
}
Run Code Online (Sandbox Code Playgroud)
但是,编译器抱怨它无法==在TValue和TValue上进行比较.这是我迄今为止提出的最好的解决方法:
DoSomething<TValue>(TValue value) {
if (value == null || value.Equals(default(TValue))) {
...
}
}
Run Code Online (Sandbox Code Playgroud)
是否有更优雅/正确的方法来解决这个问题?
我刚遇到这种情况,我认为这是一个使用default关键字的好机会.但它没有编译,我想不出为什么.以下示例说明了我的问题:
public class Test<TDataSource>
{
public IQueryable<TDataSource> DataSource { get; set; }
public bool GetOneOrDefaultResult()
{
var result = DataSource.SingleOrDefault();
return result != default(TDataSource);
}
}
Run Code Online (Sandbox Code Playgroud)
你会在第8行得到一个错误("运算符'=='不能应用于'TDataSource'和'TDataSource'类型的操作数.").我认为使用default关键字将消除引用类型和值类型之间的任何比较问题.
添加将TDataSource限制为引用类型的通用约束使得这段代码可以编译.
有人可以解释为什么编译器不会为我解决这个问题吗?只是不够聪明才能看到这会起作用吗?
这是相关的: 不能将operator ==应用于C#中的泛型类型?
[编辑] SLaks的答案给了我一些灵感,'=='运算符不起作用,但Equals函数应该.
public class Test<TDataSource>
{
public IQueryable<TDataSource> DataSource { get; set; }
public bool GetOneOrDefaultResult()
{
var result = DataSource.SingleOrDefault();
return result.Equals(default(TDataSource));
}
}
Run Code Online (Sandbox Code Playgroud)
这个编译会正常吗?
在编写包含泛型变量的类时
public class ServiceInvoker<TService> : IDisposable
{
private TService _Service;
public ServiceInvoker()
{
_Service = Activator.CreateInstance<TService>();
}
public void Invoke(Action<TService> action)
{
// CAN use null
if (_Service == null)
throw new ObjectDisposedException("ServiceInvoker");
....
}
public void Dispose()
{
// CAN'T use null
this._Service = default(TService);
}
}
Run Code Online (Sandbox Code Playgroud)
我注意到编译器允许我检查泛型变量的null,但是,当然,不允许我将其设置为null,因此我们必须使用它default(TService).
不应该编译器警告我,我使用null?或者它是否使用拳击转换到一个对象来进行null测试?