Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I create a generic method to return a specific type specified by the call?

Tags:

c#

generics

The following code gives me the errors:

Cannot implicitly convert type T to string.
Cannot implicitly convert type T to int.

What do I have to do to get this method to return the type of variable I define with T when I call it?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TestGener234
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("his first name is {0}", GetPropertyValue<string>("firstName"));
            Console.WriteLine("his age is {0}", GetPropertyValue<int>("age"));
        }

        public static T GetPropertyValue<T>(string propertyIdCode)
        {
            if (propertyIdCode == "firstName")
                return "Jim";
            if (propertyIdCode == "age")
                return 32;
            return null;
        }
    }
}

Addendum:

Here is a more complete example of why I needed the generic solution, i.e. I have a class that saves its values as strings no matter what the type, and this generic solution simply makes the calling code cleaner:

using System;
using System.Collections.Generic;

namespace TestGener234
{
    class Program
    {
        static void Main(string[] args)
        {
            List<Item> items = Item.GetItems();
            foreach (var item in items)
            {
                string firstName = item.GetPropertyValue<string>("firstName");
                int age = item.GetPropertyValue<int>("age");
                Console.WriteLine("First name is {0} and age is {1}.", firstName, age);
            }
            Console.ReadLine();
        }
    }

    public class Item
    {
        public string FirstName { get; set; }
        public string Age { get; set; }


        public static List<Item> GetItems()
        {
            List<Item> items = new List<Item>();
            items.Add(new Item { FirstName = "Jim", Age = "34" });
            items.Add(new Item { FirstName = "Angie", Age = "32" });
            return items;
        }

        public T GetPropertyValue<T>(string propertyIdCode)
        {
            if (propertyIdCode == "firstName")
                return (T)(object)FirstName;
            if (propertyIdCode == "age")
                return (T)(object)(Convert.ToInt32(Age));
            return default(T);
        }
    }
}
like image 699
Edward Tanguay Avatar asked Jan 29 '10 12:01

Edward Tanguay


3 Answers

That is troublesome; to make the compiler happy you can double-cast, but that implies a box for value types:

    public static T GetPropertyValue<T>(string propertyIdCode)
    {
        if (propertyIdCode == "firstName")
            return (T)(object)"Jim";
        if (propertyIdCode == "age")
            return (T)(object)32;
        return default(T);
    }

In reality, I think you may be better just using an object return type.

like image 198
Marc Gravell Avatar answered Oct 17 '22 20:10

Marc Gravell


This is an abuse of generics. If you have a small number of types that the generic type parameter could possibly be then just replace it with that many methods:

string GetTextProperty(string propertyName) { ... }
int GetNumberProperty(string propertyName) { ... }
Giraffe GetGiraffeProperty(string propertyName) { ... }
like image 24
Eric Lippert Avatar answered Oct 17 '22 20:10

Eric Lippert


This should work...

  public static T GetPropertyValue<T>(string propertyIdCode)
  {
     if (propertyIdCode == "firstName")
        return (T)Convert.ChangeType("Jim", typeof(T));
     if (propertyIdCode == "age")
        return (T)Convert.ChangeType(22, typeof(T));
     return default(T);
  }
like image 36
Binoj Antony Avatar answered Oct 17 '22 19:10

Binoj Antony