1

I have this code that works ok with a database with no NULL values

public T GetField<T>(SqlDataReader dr, string fieldName)
{
    return (T)dr.GetValue(dr.GetOrdinal(fieldName));
}

Then I want to control the DBNull values, because they already exist in some tables and I upgraded the function like this:

public T GetField<T>(SqlDataReader dr, string fieldName) where T : new()
{
    var value = dr.GetValue(dr.GetOrdinal(fieldName));   
    return value is DBNull ? new T() : (T)value;
}

But now, I cannot ask for GetField<string> because string has no constructor with 0 parameters.

I have tried to create another function like the Abstract one, with no restrictions and only with string type like this

public string GetField<string>(SqlDataReader dr, string fieldName)
{
    var value = dr.GetValue(dr.GetOrdinal(fieldName));   
    return value is DBNull ? "" : value.ToString();
}

but the answer is that they are ambiguous definitions, because T also includes string, even with the restriction applied.

I could create independent functions for each datatype, but I rather prefer the abstract solution because it is way much cleaner.

Did I miss something?

Thanks!

2
  • 2
    It's not clear what you mean by "another function like the abstract one" - which abstract what? You haven't shown any abstract methods or classes... did you mean generic? (Generic and abstract mean very different things in C#.) Commented Nov 19, 2014 at 17:15
  • Yes, you are right, I meant Generic Commented Nov 20, 2014 at 13:09

2 Answers 2

5

Your final method would fail because it's trying to declare a type parameter called string.

I suggest you add another overload without the constraint on T, but with a default value:

public T GetField<T>(SqlDataReader dr, string fieldName, T defaultValue)
{
    var value = dr.GetValue(dr.GetOrdinal(fieldName));   
    return value is DBNull ? defaultValue : (T) value;
}

Then you'd call it as:

string x = foo.GetField(reader, "field", "");

... with the added benefit that the method isn't string-specific.

Sign up to request clarification or add additional context in comments.

2 Comments

@JeroenMostert: Yup, fixed.
The default value is a nice feature to have and I have included it, thanks!
2

Here's one approach:

public T GetField<T>(SqlDataReader dr, string fieldName)
{
    var value = dr.GetValue(dr.GetOrdinal(fieldName));
    return value is DBNull ? default(T) : (T) value;
}

This has the added benefit of working with nullable types. Then you'd call that as:

string x = foo.GetField<string>(reader, "field") ?? "";

Which is deliberately contrived in this case -- Jon's version with a default suits you better if usually you want something other than null returned.

1 Comment

That was exactly was I was looking for. Mixing both solutions give me the flexibility to answer all my scenarios. Many thanks!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.