Operator== overload problem

T

Tony

I have an operator== overload that compares two items and returns a new
class as the result of the comparison (instead of the normal bool)

I then get an ambiguous operater compile error when I attempt to check to
see if the object is null:
"The call is ambiguous between the following methods or properties:
'TestObject.operator ==(TestObject, string)' and 'TestObject.operator
==(TestObject, TestObject)"

Does anyone have any idea how to correct this problem?

Example source follows:

Thanks,
Tony

internal class Condition
{
}

internal class TestObject
{
public static Condition operator==(TestObject oTestObject, string
sValue)
{
return new Condition(); // a stub for illistration purposes
}

public static Condition operator!=(TestObject oTestObject, string
sValue)
{
return new Condition(); // a stub for illistration purposes
}

public static Condition operator==(TestObject oTestObject1, TestObject
oTestObject2)
{
return new Condition(); // a stub for illistration purposes
}

public static Condition operator!=(TestObject oTestObject1, TestObject
oTestObject2)
{
return new Condition(); // a stub for illistration purposes
}

public override int GetHashCode()
{
return base.GetHashCode();
}

public override bool Equals(object aObject)
{
return base.Equals(aObject);
}

}

internal class Test
{
void Testmethod()
{
TestObject oTestObject = null;

if (oTestObject == null) // compile error occurs on this line
oTestObject = new TestObject();
}
}
 
G

Guest

Yes. Don't overload == for anything except value types.

I don't understand why you would return other than a bool? If you want a
method to return an instance of a class based upon the comparison, then write
a method that calls the comparison and returns the class instance based on
the result but don't overload the comparison.

When you do have to overload equivelence in objects (and I recommend doing
it more often than not) overload Object.Equals(), but you still have to
return a bool. You can't change the return type in an overload. You could,
but I wouldn't recommend it, use the keyword "new" instead of "override" to
hide the original operator or method and then you could return a different
type.

Hiding base class members should be done with caution and great reserve.

HTH
 
T

Tony

I'm doing this because the classes I'm building allow me to generate SQL
using the C# syntax.
The details get a bit more technical, but I will give it a try.

Select.Where( Table1["IdColumn"] == Table2["IdColumn"] & Table1["Name"] ==
Table2["Name"]);

The above C# code generates the following SQL:
"Where Table1.IdColumn = Table2.IdColumn and Table1.Name = Table2.Name"

Table1["IdColumn"] == Table2["IdColumn"] generates a Condition object
returned from the Columns operator==:
Where( ) accepts a Condition.
You can create a new Condition by: Condition & Condition and so forth.

The problem is when I need to check the value of my Column class (returned
from a Table) to see if it's null or for any other reason.

Column oColumn = oTable1["IdColumn"];

if (oColumn == null) // generates the ambiguous error

however, I have found a work around by casting it to object first to do a
reference compare but it's less that intuitive when you see it:

if ((object)oColumn == null) //. compiles fine

Tony
 
T

Tony

The problem has nothing to do with returning something other than bool, the
same happens in that case also:

internal class Condition
{

}

internal class TestObject
{

public static bool operator==(TestObject oTestObject, string sValue)
{
return true; // a stub for illistration purposes
}

public static bool operator !=(TestObject oTestObject, string sValue)
{
return true; // a stub for illistration purposes
}

public static bool operator ==(TestObject oTestObject1, TestObject
oTestObject2)
{
return true; // a stub for illistration purposes
}

public static bool operator !=(TestObject oTestObject1, TestObject
oTestObject2)
{
return true; // a stub for illistration purposes
}

public override int GetHashCode()
{
return base.GetHashCode();
}

public override bool Equals(object aObject)
{
return base.Equals(aObject);
}

}


internal class Test
{
void Testmethod()
{
TestObject oTestObject = null;

if (oTestObject == null) // compiler error
oTestObject = new TestObject();
}
}
 
N

Nicholas Paldino [.NET/C# MVP]

Tony,

In your case, you want to write the code like this:

if (oTestObject == (TestObject) null) // compile error occurs on this line
oTestObject = new TestObject();

The reason you get the ambiguity error is because null doesn't have a
type.

What you might want to do is have a static instance of your test object
which represents null and replace null with that.

Hope this helps.
 
T

Tony

Thanks, but that doesn't work if the operator== returns an object and not
bool.

This only thing I have come up with that works is to cast it to (object)
first to do a reference compare, but it's not very intuitive.

if ((object)oTestObject == null)
oTestObject = new TestObject();

Tny


Nicholas Paldino said:
Tony,

In your case, you want to write the code like this:

if (oTestObject == (TestObject) null) // compile error occurs on this
line
oTestObject = new TestObject();

The reason you get the ambiguity error is because null doesn't have a
type.

What you might want to do is have a static instance of your test object
which represents null and replace null with that.

Hope this helps.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Tony said:
I have an operator== overload that compares two items and returns a new
class as the result of the comparison (instead of the normal bool)

I then get an ambiguous operater compile error when I attempt to check to
see if the object is null:
"The call is ambiguous between the following methods or properties:
'TestObject.operator ==(TestObject, string)' and 'TestObject.operator
==(TestObject, TestObject)"

Does anyone have any idea how to correct this problem?

Example source follows:

Thanks,
Tony

internal class Condition
{
}

internal class TestObject
{
public static Condition operator==(TestObject oTestObject, string
sValue)
{
return new Condition(); // a stub for illistration purposes
}

public static Condition operator!=(TestObject oTestObject, string
sValue)
{
return new Condition(); // a stub for illistration purposes
}

public static Condition operator==(TestObject oTestObject1,
TestObject oTestObject2)
{
return new Condition(); // a stub for illistration purposes
}

public static Condition operator!=(TestObject oTestObject1,
TestObject oTestObject2)
{
return new Condition(); // a stub for illistration purposes
}

public override int GetHashCode()
{
return base.GetHashCode();
}

public override bool Equals(object aObject)
{
return base.Equals(aObject);
}

}

internal class Test
{
void Testmethod()
{
TestObject oTestObject = null;

if (oTestObject == null) // compile error occurs on this line
oTestObject = new TestObject();
}
}
 
N

Nick Hounsome

Tony said:
I have an operator== overload that compares two items and returns a new
class as the result of the comparison (instead of the normal bool)

I then get an ambiguous operater compile error when I attempt to check to
see if the object is null:
"The call is ambiguous between the following methods or properties:
'TestObject.operator ==(TestObject, string)' and 'TestObject.operator
==(TestObject, TestObject)"

Does anyone have any idea how to correct this problem?

Example source follows:

Thanks,
Tony

internal class Condition
{
}

internal class TestObject
{
public static Condition operator==(TestObject oTestObject, string
sValue)
{
return new Condition(); // a stub for illistration purposes
}

public static Condition operator!=(TestObject oTestObject, string
sValue)
{
return new Condition(); // a stub for illistration purposes
}

public static Condition operator==(TestObject oTestObject1,
TestObject oTestObject2)
{
return new Condition(); // a stub for illistration purposes
}

public static Condition operator!=(TestObject oTestObject1,
TestObject oTestObject2)
{
return new Condition(); // a stub for illistration purposes
}

public override int GetHashCode()
{
return base.GetHashCode();
}

public override bool Equals(object aObject)
{
return base.Equals(aObject);
}

}

internal class Test
{
void Testmethod()
{
TestObject oTestObject = null;

if (oTestObject == null) // compile error occurs on this line
oTestObject = new TestObject();
}
}

There are 2 problems.

The error is because the compiler cannot tell whether null is supposed to be
a TestObject or a string.
[ essentially the call is TestObject.operator==(oTestObject,null) ]

The major error is that Equals() and ==() can return different values which
is grossly counter intuitive.

The "standard" interpretation of Equals() is that 2 things are NEVER equal
if they are of different types (except possibly stuff link equivalent
numeric valus). A TestObject is not a kind of string so
oTestObject.Equals("hello")
should return false (or your Condition equivalent) and consistency then
demands that
oTestObject == "hello"
should also always return false which in turn makes it unnecessary.
 
F

Frans Bouma [C# MVP]

Tony said:
I have an operator== overload that compares two items and returns a
new class as the result of the comparison (instead of the normal bool)

I then get an ambiguous operater compile error when I attempt to
check to see if the object is null:
"The call is ambiguous between the following methods or properties:
'TestObject.operator ==(TestObject, string)' and 'TestObject.operator
==(TestObject, TestObject)"

this is logical, as it matches with both. I had the same prob, and
solved it as below.

What you should do is this:
instead of creating overloads for string AND TestObject, make 1
method, with type 'object'.

Internally, test for the type of object or null. This way you can
avoid the compilation error and IF you ever need an overload, you can
then also use in your code:

testobject==DBNull.Value

which represents testing for null (for example, don't know where you
use it for).

FB

internal class Condition
{
}

internal class TestObject
{
public static Condition operator==(TestObject oTestObject,
string sValue)
{
return new Condition(); // a stub for illistration purposes
}

public static Condition operator!=(TestObject oTestObject,
string sValue)
{
return new Condition(); // a stub for illistration purposes
}

public static Condition operator==(TestObject oTestObject1,
TestObject oTestObject2)
{
return new Condition(); // a stub for illistration purposes
}

public static Condition operator!=(TestObject oTestObject1,
TestObject oTestObject2)
{
return new Condition(); // a stub for illistration purposes
}

public override int GetHashCode()
{
return base.GetHashCode();
}

public override bool Equals(object aObject)
{
return base.Equals(aObject);
}

}

internal class Test
{
void Testmethod()
{
TestObject oTestObject = null;

if (oTestObject == null) // compile error occurs on this
line oTestObject = new TestObject();
}
}



--
 
F

Frans Bouma [C# MVP]

Tony said:
I'm doing this because the classes I'm building allow me to generate
SQL using the C# syntax.
The details get a bit more technical, but I will give it a try.

Select.Where( Table1["IdColumn"] == Table2["IdColumn"] &
Table1["Name"] == Table2["Name"]);

The above C# code generates the following SQL:
"Where Table1.IdColumn = Table2.IdColumn and Table1.Name =
Table2.Name"

Table1["IdColumn"] == Table2["IdColumn"] generates a Condition
object returned from the Columns operator==:
Where( ) accepts a Condition.
You can create a new Condition by: Condition & Condition and so forth.

The problem is when I need to check the value of my Column class
(returned from a Table) to see if it's null or for any other reason.

Column oColumn = oTable1["IdColumn"];

if (oColumn == null) // generates the ambiguous error

however, I have found a work around by casting it to object first to
do a reference compare but it's less that intuitive when you see it:

if ((object)oColumn == null) //. compiles fine

if you're using it for SQL predicate production, you should go for a
single method with 'object' and compare with DBNull.Value. I do that
too in my O/R mapper, so I can do:

Predicate filter = (CustomerFields.CompanyName == DBNull.Value);

which produces a [Customers].[CompanyName] IS NULL predicate in SQL.

FB

--
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top