Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generic methods returning simple types

Tags:

c#

generics

Ok, I've got a bit of code that I don't like very much. Given that I didn't write it and merely inherited it, it occurs to me that I could clean it up a little. Basically, we have an object for settings that is persisted with NHibernate. I won't bore you with the implementation details except to say that it contains a dictionary that has the actual values we're keeping in the database.

Our typical property implementation looks like this:

public string MyDumbProperty
{
get { return GetStringValue("MyDumbProperty", string.Empty); }
set { SetValue("MyDumbProperty", value);}
}

Now, it's probably obvious from the implementation above that we have separate Getxxxx methods for each of the types we return (strings, ints, longs, floats, etc.), with the second parameter being a default value. What I want is to be able to do something like the following:

public string MyDumbProperty
{
get { return GetValue("MyDumbProperty", string.Empty); }
set { SetValue("MyDumbProperty", value);}
}

I have a couple of reasons for wanting to do this. The big one is that I have a personal dislike of methods named based on what types of parameters they take. The second is that I'd like to make a resharper template for this crap. Then I could just fill in the name of the property and the type and be done (presuming that resharper could give a reasonable default value for the type).

I had thought of making a generic method GetValue that returned a T, but I'm not sure how I need to set up the generic constraints so this is doable. The types being returned from this will all be basic types (strings, ints, etc). There are a couple that return arrays, but I could always do something different on those. This isn't a high priority issue, by any means, but it annoys me every time I see it. I just think there should be a better way to do this.

I suppose a first step would be to just rename the various methods. Since they vary on what type is being passed for the default in the second parameter, I could at least coerce them to the same name. But I could I do better than that? It would be great if I could get rid of the multiple bits of repetitive code in each method that are only different in terms of the datatype being used (TryParse in all the numeric ones).

like image 938
Will Gant Avatar asked Jan 21 '26 23:01

Will Gant


2 Answers

I think you might be able to get away with a generic method if the guts of it aren't too complicated. For example, maybe something like this:

public T GetValue<T>(string name, T ifNull) where T : IConvertible
{
    string value = GetProperty(name);
    if (value == null)
        return ifNull;
    try
    {
        return (T)Convert.ChangeType(value, typeof(T));
    }
    catch
    {
        return ifNull;
    }
}

For arrays, you might need a GetArrayValue function that does something different.

like image 141
Gabe Avatar answered Jan 23 '26 15:01

Gabe


You can use default(T) to get the default value of a type.

public T Get<T>(string propertyName)
{
    object obj;
    if (propertyBag.TryGetValue(propertyName, out obj)) {
        return (T)obj;
    }
    if(typeof(T) == typeof(string)) {
        return String.Empty;
    }
    return default(T);
}

UPDATE

As an alternative you could have two overloads, one accepting an explicit default value.

public T Get<T>(string propertyName)
{
    return Get<T>(propertyName, default(T));
}

public T Get<T>(string propertyName, T defaultValue)
{
    object obj;
    if (propertyBag.TryGetValue(propertyName, out obj)) {
        return (T)obj;
    }
    return defaultValue;
}
like image 34
Olivier Jacot-Descombes Avatar answered Jan 23 '26 14:01

Olivier Jacot-Descombes



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!