1

I need a generic method that can return a value parsed from a string

public T GetDefaultValue<T>(){
    // if typeof(T) is Double it should try to parse some string (supposedly which's been read from DB), 
    // and return Double value, or if typeof(T) is Int, then it should parse the string 
    //into Int, and finally if typeof(T) is a string, then no parsing is needed.
}

UPD... Why can't I check if T is some certain type and use Parse method accordingly?

2

5 Answers 5

2

Convert.ChangeType could be used to make your conversions.

public T Parse<T>(string input)
{
     return (T)Convert.ChangeType(input, typeof(T));
}

int x = Parse<int>("1");
double y = Parse<double>("1.0");
string z = Parse<string>("hey");

Notice that to even make this work, you are specifying your types? What's the savings over using int.Parse (or TryParse), double.Parse, etc.?

And since you mention your inputs are likely coming from a database, and still knowing that to even use the above method you have to specify the type parameter already, I would encourage you to (a) know and trust your types and (b) use existing functionality to obtain values from data sources. No need to convert something to a string and then convert it back to whatever data type you wish it to be.

int x = myDataRow.Field<int>("Column1"); // or
int x = (int)myDataRow["Column1"];

This also supports if the numeric values could be nullable in the database.

int? x = myDataRow.Field<int?>("Column1"); // or
int x = myDataRow.Field<int?>("Column1").GetValueOrDefault(); // normalize nulls to 0
Sign up to request clarification or add additional context in comments.

Comments

1

What is the point of using generics for this? You lose all benefits of generics by checking for actual types.

Just have three overloads, one for int, one for double and (the probably unneeded) string.

2 Comments

if I'm remembering right methods' signatures cannot be different only in return types
@Agzam - You recall correctly. But if you pass an int versus a double versus a string, they are different parameter types.
1

I would just make string extensions like

public static int xToInt(this string source, int alternate = 0)
{
   int result;
   return (int.TryParse(source, out result) ? result : alternate);
}

And then just create one for Double and you could then use it by doing

int someNumber  = "123456".xToInt();
int someNumber2 = "omg!".xToInt(333);

Comments

1

You can do something like this without generics. Why use a sword when all you need is a needle

class Test
    {
        public string ReadFromDb()
        {
            //Do your db work here
            return "";
        }

        public bool GetDefaultValue(ref int t1)
        {
            t1 = Int32.Parse(ReadFromDb());
            return true;
        }

        public bool GetDefaultValue(ref double t1)
        {
            t1 = Double.Parse( ReadFromDb() );
            return true;
        }

        public bool GetDefaultValue(ref string t1)
        {
            t1 = ReadFromDb();
            return true;
        }
    }

Comments

1

I wrote generic methods that use reflection to search an appropriate Parse method and call it. But they won't work if you want to transform string to string since string doesn't have a Parse method. So you'll need to add a special case for string.

I don't understand why your function is called GetDefaultValue either. Why not Parse, TryParse, ConvertFromString or something like that? When seeing a function called GetDefaultValue, I don't think of a parsing function.

Check this old question: Is it possible to make a generic number parser in C#? which has several relevant answers.


And my old answer from there:

I have written some code that uses reflection to find Parse/TryParse methods on a type and access these from generic functions:

private static class ParseDelegateStore<T>
{
    public static ParseDelegate<T> Parse;
    public static TryParseDelegate<T> TryParse;
}

private delegate T ParseDelegate<T>(string s);
private delegate bool TryParseDelegate<T>(string s, out T result);


public static T Parse<T>(string s)
{
    ParseDelegate<T> parse = ParseDelegateStore<T>.Parse;
    if (parse == null)
    {
        parse = (ParseDelegate<T>)Delegate.CreateDelegate(typeof(ParseDelegate<T>), typeof(T), "Parse", true);
        ParseDelegateStore<T>.Parse = parse;
    }
    return parse(s);
}

public static bool TryParse<T>(string s, out T result)
{
    TryParseDelegate<T> tryParse = ParseDelegateStore<T>.TryParse;
    if (tryParse == null)
    {
        tryParse = (TryParseDelegate<T>)Delegate.CreateDelegate(typeof(TryParseDelegate<T>), typeof(T), "TryParse", true);
            ParseDelegateStore<T>.TryParse = tryParse;
    }
    return tryParse(s, out result);
}

https://github.com/CodesInChaos/ChaosUtil/blob/master/Chaos.Util/Conversion.cs

But I haven't tested them too much, so they might stiff have some bugs/not work correctly with every type. The error handling is a bit lacking too.

And they have no overloads for culture invariant parsing. So you probably need to add that.

Comments

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.