implicit conversion - what is guaranteed?

B

Berryl Hesh

Below is a dialog I am having with Charlie Poole of NUnit in his user forum.
Of more concern than NUnit usage, I'm not sure whether there is something
inherently vague about implicit conversion or it's the way I'm using it (or
both).

Any ideas? Thanks! BH
Subject: [nunit-discuss] Is.EqualTo calling ToString on implicit
conversion

I have a class called a DatePoint that wraps a DateTime. The purpose is to
conveniently control precision in cases where time zone, seconds, etc. are
not relevant or could be detrimental to a given requirement.

Is.EqualTo fails when comparing a DateTime to a DatePoint, and only then
(tests && code below), because it calls DatePoint.ToString() instead of
DatePoint.Equals(object).

Any suggestions?

Thanks for sharing`! BH

// class code that does the implicit conversion

public static implicit operator DateTime(DatePoint datepoint) {
return datepoint._wrappedDate;
}

public static implicit operator DatePoint(DateTime datetime) {
return new DatePoint(datetime, TimeSlice.Second);
}

// testing code

[Test]
public void Implicit_Equality_DatePoint_DateTime_OpEq() {
Assert.That(DatePoint.Today == DateTime.Today);
Assert.That(DateTime.Today == DatePoint.Today);
Assert.That(DatePoint.Tomorrow != DateTime.Today);
Assert.That(DateTime.Today != DatePoint.Tomorrow);
}

[Test]
public void
Implicit_Equality_DatePoint_DateTime_Equals() {
Assert.That(DatePoint.Today.Equals(DateTime.Today));
Assert.That(DateTime.Today.Equals(DatePoint.Today));
Assert.That(DatePoint.Today, Is.EqualTo(DatePoint.Today));
Assert.That(DateTime.Today, Is.EqualTo(DatePoint.Today));
Assert.That(DatePoint.Today, Is.EqualTo(DateTime.Today)); ==>
Only failure
}


- Hide quoted text -
- Show quoted text -
Hi Berryl,
Where are you seeing the use of ToString()? Of course, it is used in
displaying the error message, but NUnit stopped comparing string
representations internally a while back.
As the 2.4.8 code is written, you should be getting the result
of expected.Equals(actual). My guess, however, is that DateTime
will not find the implicit conversion in this context, because
actual declared as an object, and DateTime knows nothing about
DatePoints.
In general, implicit conversion operators can only be relied
upon for one level of conversion, at one specific point in
the code. In this case, your DatePoint is simply an object
by the time it is handed over to te low-level routines. The
only way we could make this work is if we returned
expected.Equals(actual) || actual.Equals(expected)
but I'm afraid that would mess up more folks than it would help.

The order of execution is below, as is the error message. Do you know
of a good summary of what is guaranteed on an implicit conversion? Or
if I can somehow make the DateTime aware of it through an extension
method?

1 Smack.Core.Tests.DLL!
Smack.Core.Tests.Domain.Temporal.DatePointTest.Implicit_Equality_DatePoint_DateTime_Equals
() Line 94 + 0x2d bytes
2 Smack.Core.DLL!Smack.Core.Domain.Temporal.DatePoint.implicit
operator Smack.Core.Domain.Temporal.DatePoint(System.DateTime datetime
= {12/25/2008 12:00:00 AM}) Line 202
3 Smack.Core.Tests.DLL!
Smack.Core.Tests.Domain.Temporal.DatePointTest.Implicit_Equality_DatePoint_DateTime_Equals
() Line 94 + 0x63 bytes [External Code]
4 Smack.Core.DLL!Smack.Core.Domain.Temporal.DatePoint.ToString(string
format = null, System.IFormatProvider formatProvider = {}) Line 222
[External Code]

TestCase
'Smack.Core.Tests.Domain.Temporal.DatePointTest.Implicit_Equality_DatePoint_DateTime_Equals'
failed:
Expected: 2008-12-25 00:00:00.000
But was: <12/25/2008>

Smack.Core.DLL!Smack.Core.Domain.Temporal.DatePoint.ToString(string
format = null, System.IFormatProvider formatProvider = {}) Line 222 C#
[External Code]
Smack.Core.Tests.DLL!
Smack.Core.Tests.Domain.Temporal.DatePointTest.Implicit_Equality_DatePoint_DateTime_Equals
() Line 94 + 0x63 bytes C#
[External Code]
 
B

Berryl Hesh

You are correct-o-mundo Pete. Thank you

Berryl


Peter Duniho said:
There is nothing "inherently vague about implicit conversion" as far as C#
is concerned. The rules are well-defined.

You seem to be having an issue with some support class in NUnit, and for
issues regarding that, I would expect the developer of NUnit to be the
last word on what's supposed to happen, what's supported, that sort of
thing.

The reply from Mr. Poole seems pretty clear to me, even without knowing
anything about the NUnit support class. In particular, he's clearly
explained to you that at the point where the comparison is actually being
done, the only type his code knows is "object". Implicit conversions in
C# require a _compile-time_ context, using the static typing of the
variables in use.

You seem to be expecting the implicit conversion to occur dynamically at
run-time, which simply doesn't happen in C# (not automatically, anyway).

In addition to Mr. Poole's comment about one possible change he could make
(testing the converse equalities and or-ing the result), another option
would be for NUnit to use reflection to look for the implicit conversion
and execute it dynamically. But it may be that would produce unexpected
effects for other people, just as the converse equality test might. I
don't know enough about his users to know whether that would be a boon or
bane for them.

In any case, without explicit support from the NUnit code, there's nothing
about C# that would cause the implicit conversion to be respected or used
in this case.

Pete
 

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