delegate usage?

E

Eric

I have a number of static helper methods to read in data from an
IDataReader; one of the services provided by this helper class is the
ability to return a nullable type as needed, for instance:
public static DateTime? GetNullableDateTime(object value) {...}
public static int? GetNullableInterger(object value) {...}
etc.

In writing tests for this class, all of the GetNullable type methods should
in fact return null if the value passed in is either null or DBNull.Value,
so you could have the following valid but cumbersome tests:
[Test]
public void DateTimeNullable_NullDateTimeIfNull() {
_assertNullDateTimeFor(null);
_assertNullDateTimeFor(DBNull.Value);
}
private static void _assertNullDateTimeFor(object value) {
Assert.That(DataReaderHelper.GetNullableDateTime(value), Is.Null); }

[Test]
public void IntegerNullable_NullIntegerIfNull() {
_assertNullIntegerFor(null);
_assertNullIntegerFor(DBNull.Value);
}
private static void _assertNullIntegerFor(object value) {
Assert.That(DataReaderHelper.GetNullableInteger(value), Is.Null); }

----------------------------

Too make the test class less cumbersome and noisy, I'd rather have one
assertion helper that can invoke whatever nullable method passed into it,
but I'm not getting my head around how to do this very well.
The assert method should be something like:
private static void
_assertNullReturnedForNullableEquivalents(delegateMethod dm) {
Assert.That(dm(null), Is.Null);
Assert.That(dm(DBNull), Is.Null);
}

The test method should look something like:

[Test]
public void DateTimeNullable_NullDateTimeIfNull() {
assertNullReturnedForNullableEquivalents(DataReaderHelper.GetNullableDateTime)
}

I need a delegate that looks something like
delegate T delegateMethod<T>(object value);
 
G

Göran Andersson

Eric said:
I have a number of static helper methods to read in data from an
IDataReader; one of the services provided by this helper class is the
ability to return a nullable type as needed, for instance:
public static DateTime? GetNullableDateTime(object value) {...}
public static int? GetNullableInterger(object value) {...}
etc.

In writing tests for this class, all of the GetNullable type methods should
in fact return null if the value passed in is either null or DBNull.Value,
so you could have the following valid but cumbersome tests:
[Test]
public void DateTimeNullable_NullDateTimeIfNull() {
_assertNullDateTimeFor(null);
_assertNullDateTimeFor(DBNull.Value);
}
private static void _assertNullDateTimeFor(object value) {
Assert.That(DataReaderHelper.GetNullableDateTime(value), Is.Null); }

[Test]
public void IntegerNullable_NullIntegerIfNull() {
_assertNullIntegerFor(null);
_assertNullIntegerFor(DBNull.Value);
}
private static void _assertNullIntegerFor(object value) {
Assert.That(DataReaderHelper.GetNullableInteger(value), Is.Null); }

----------------------------

Too make the test class less cumbersome and noisy, I'd rather have one
assertion helper that can invoke whatever nullable method passed into it,
but I'm not getting my head around how to do this very well.
The assert method should be something like:
private static void
_assertNullReturnedForNullableEquivalents(delegateMethod dm) {
Assert.That(dm(null), Is.Null);
Assert.That(dm(DBNull), Is.Null);
}

The test method should look something like:

[Test]
public void DateTimeNullable_NullDateTimeIfNull() {
assertNullReturnedForNullableEquivalents(DataReaderHelper.GetNullableDateTime)
}

I need a delegate that looks something like
delegate T delegateMethod<T>(object value);

Hmm... I don't really see the point...

Why not simply:

private T? GetNullable<T>(object obj) where T : struct {
if (obj == null) return null;
if (obj is DBNull) return null;
if (obj is T) return (T)obj;
throw new ArgumentException("Type of object does not match generic type
of method.", "obj");
}
 
E

Eric

Then I think I have a different challenge since I'm reading in from a db.
Here is your method, cleaned up a touch:
private static T? GetNullable<T>(object obj) where T : struct {
if (obj == null) return null;
if (obj is DBNull) return null;
if (obj is T?) return (T) obj;
throw new ArgumentException("Type of object does not match generic
type of method.", "obj");
}

The methods use each underlying type's TryParse() to see if it is indeed the
right type, so for DateTime? there is:

public static DateTime? GetNullableDateTime(object value) {
DateTime? result = null;
if (_isNotNull(value)) { // (check for null & DBNull
<------ tryParse section ------->
DateTime parsedDateTime;
if (DateTime.TryParse(value.ToString(), out
parsedDateTime)) {
result = parsedDateTime;
}
}
<------ tryParse section ------->
return result;
}

How would I do that tryParse section generically?

TIA,
Eric

Göran Andersson said:
Eric said:
I have a number of static helper methods to read in data from an
IDataReader; one of the services provided by this helper class is the
ability to return a nullable type as needed, for instance:
public static DateTime? GetNullableDateTime(object value) {...}
public static int? GetNullableInterger(object value) {...}
etc.

In writing tests for this class, all of the GetNullable type methods
should in fact return null if the value passed in is either null or
DBNull.Value, so you could have the following valid but cumbersome tests:
[Test]
public void DateTimeNullable_NullDateTimeIfNull() {
_assertNullDateTimeFor(null);
_assertNullDateTimeFor(DBNull.Value);
}
private static void _assertNullDateTimeFor(object value) {
Assert.That(DataReaderHelper.GetNullableDateTime(value), Is.Null); }

[Test]
public void IntegerNullable_NullIntegerIfNull() {
_assertNullIntegerFor(null);
_assertNullIntegerFor(DBNull.Value);
}
private static void _assertNullIntegerFor(object value) {
Assert.That(DataReaderHelper.GetNullableInteger(value), Is.Null); }

----------------------------

Too make the test class less cumbersome and noisy, I'd rather have one
assertion helper that can invoke whatever nullable method passed into it,
but I'm not getting my head around how to do this very well.
The assert method should be something like:
private static void
_assertNullReturnedForNullableEquivalents(delegateMethod dm) {
Assert.That(dm(null), Is.Null);
Assert.That(dm(DBNull), Is.Null);
}

The test method should look something like:

[Test]
public void DateTimeNullable_NullDateTimeIfNull() {

assertNullReturnedForNullableEquivalents(DataReaderHelper.GetNullableDateTime)
}

I need a delegate that looks something like
delegate T delegateMethod<T>(object value);

Hmm... I don't really see the point...

Why not simply:

private T? GetNullable<T>(object obj) where T : struct {
if (obj == null) return null;
if (obj is DBNull) return null;
if (obj is T) return (T)obj;
throw new ArgumentException("Type of object does not match generic type of
method.", "obj");
}
 
G

Göran Andersson

Eric said:
Then I think I have a different challenge since I'm reading in from a db.
Here is your method, cleaned up a touch:
private static T? GetNullable<T>(object obj) where T : struct {
if (obj == null) return null;
if (obj is DBNull) return null;
if (obj is T?) return (T) obj;

No, it's not a nullable T, it's just the type T. The result that comes
from the database still looks the same as it did before the nullable
types existed.
throw new ArgumentException("Type of object does not match generic
type of method.", "obj");
}

The methods use each underlying type's TryParse() to see if it is indeed the
right type, so for DateTime? there is:

public static DateTime? GetNullableDateTime(object value) {
DateTime? result = null;
if (_isNotNull(value)) { // (check for null & DBNull
<------ tryParse section ------->
DateTime parsedDateTime;
if (DateTime.TryParse(value.ToString(), out
parsedDateTime)) {
result = parsedDateTime;
}
}
<------ tryParse section ------->
return result;
}

How would I do that tryParse section generically?

TIA,
Eric

Why would you convert the DateTime value into a string and then parse
the string? If it's a datetime type in the database, it will arrive as a
DateTime value in your result. You just have to cast it to DateTime to
unbox the value.
 
E

Eric

Goran

My original code sample were based on a book I just bought on building a
..Net application with a Domain Driven Design. I bought it so I could improve
my skills in this area. I will ask the author, but I assume he has code like
this for a combination of reasons including it's part of a working code base
for him, it isn't the gist of what hes presenting in the book, it ain't
broke, and possibly his experience is to use or deal with datatypes stored
as strings (the TryParse stuff).

I posted my original post to improve my skills at using delegates, and make
for more compact and less noisy testing - something I'd still like to know
how to do.

After testing what you came up with, it really just takes two lines of code
to do what I need as follows:
private static T? GetNullable<T>(object obj) where T : struct {
if (obj is T?) return (T) obj;
return null;
}

Your post was fantastic, and helped me get a bit more comfortable with
generics. Thank you much.

Eric
 
P

Pavel Minaev

Hmm... I don't really see the point...

Why not simply:

private T? GetNullable<T>(object obj) where T : struct {
        if (obj == null) return null;

Given that T is restricted to "struct", which means that it cannot be
Nullable, why the null check?
 
G

Göran Andersson

Eric said:
My original code sample were based on a book I just bought on building a
.Net application with a Domain Driven Design. I bought it so I could improve
my skills in this area. I will ask the author, but I assume he has code like
this for a combination of reasons including it's part of a working code base
for him, it isn't the gist of what hes presenting in the book, it ain't
broke,

Just because the code isn't broken, doesn't mean that it's good. Your
intention should be to write robust, managable code, not just code that
works.

If you, as an example, get a DateTime value from the database, there is
no reason to do anything with it other than just verifying that the data
type is the one that you expect.

The lazy way of doing it is to convert it to a string whatever it
happens to be, and then try to parse it into the type you want it to be.
It works, but it adds some string handling for every value that you
read, and some extra objects for the garbage collector to take care of.
Additionally, if the type of the data that you get isn't what you
expected, you may get some really weird results.
and possibly his experience is to use or deal with datatypes stored
as strings (the TryParse stuff).

If all the data would actually be stored as strings in the database, the
database design sucks...
I posted my original post to improve my skills at using delegates, and make
for more compact and less noisy testing - something I'd still like to know
how to do.

After testing what you came up with, it really just takes two lines of code
to do what I need as follows:
private static T? GetNullable<T>(object obj) where T : struct {
if (obj is T?) return (T) obj;
return null;
}

You have removed the error handling, which isn't a very good idea. There
are three possible scenarios: the value is DBNull, the value is the type
that you specified, or there is something wrong and the type is
something different. In the last case your code will still return null,
so you don't get any indication that there is something wrong with the code.

If there is something wrong with the code, you want to know it before it
corrupts all the data in the database. An error message may seem bad,
but ignoring errors can get so much worse...
 
G

Göran Andersson

Pavel said:
Given that T is restricted to "struct", which means that it cannot be
Nullable, why the null check?

Because the object is not restricted to the type T.

The null check may be superflous if the data comes from the database,
but it's exactly to the specification from the OP.
 

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