如何创建一个泛型方法来返回调用指定的特定类型?

时间:2010-01-29 12:56:20

标签: c# generics

以下代码给出了错误:

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

当我调用它时,我该怎样做才能让这个方法返回我用T定义的变量类型?

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;
        }
    }
}

附录:

这是一个更完整的示例,说明为什么我需要通用解决方案,即我有一个类将值保存为字符串,无论类型如何,这个通用解决方案只是使调用代码更清晰:

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);
        }
    }
}

9 个答案:

答案 0 :(得分:13)

这很麻烦;为了使编译器满意,你可以进行双重转换,但这意味着值类型的框:

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

实际上,我认为使用object返回类型可能会更好。

答案 1 :(得分:4)

这是滥用泛型。如果泛型类型参数可能有少量类型,那么只需用许多方法替换它:

string GetTextProperty(string propertyName) { ... }
int GetNumberProperty(string propertyName) { ... }
Giraffe GetGiraffeProperty(string propertyName) { ... }

答案 2 :(得分:2)

这应该有用......

  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);
  }

答案 3 :(得分:1)

GetPropertyValue<string>("age")想要返回一个字符串。将其更改为GetPropertyValue<int>("age"),只要“年龄”是您的参数值,它就会有效。

您的实现最好获取泛型参数T的类型,以便选择返回的内容而不是基于函数参数。

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 (typeof(T) == typeof(string) && propertyIdCode == "firstName")
                return "Jim";
            if (typeof(T) == typeof(string) && propertyIdCode == "age")
                return "32";
            if (typeof(T) == typeof(int) && propertyIdCode == "age")
                return 32;
            throw (new ArgumentException());
        }
    }
}

答案 4 :(得分:1)

您可以从GetPropertyValue返回对象然后进行强制转换。您正在尝试使用泛型方法根据输入参数返回特定类型。听起来令人困惑: - )

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

然后投射(int)GetPropertyValue("age");

答案 5 :(得分:1)

通常当您在通用方法内部进行转换时,这是一个设计问题。通常,您希望在方法中保留类型泛型无强制转换,不基于类型进行拼写),如下所示:

public class Properties<T>
{
    private Dictionary<string, T> _dict = new Dictionary<string, T>();

    public void SetPropertyValue<T>(string propertyIdCode, T value)
    {
        _dict[propertyIdCode] = value;
    }

    public T GetPropertyValue<T>(string propertyIdCode)
    {
        return _dict[propertyIdCode];
    }
}

另一方面,如果你想通过他们的名字访问对象的属性(看起来这就是你正在做的事情,对不起,如果我弄错了),正确的方法是使用反射({{3 }}):

public object GetPropertyValue(object obj, string propertyIdCode)
{
    PropertyInfo pinfo = obj.GetType().GetProperty(propertyIdCode);
    return pinfo.GetValue(obj, null);
}

答案 6 :(得分:0)

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

答案 7 :(得分:0)

Marc的双重演示示例是让编译器正常运行的正确方法。

您可以为每种值类型编写sperate方法,并为引用类型提供通用方法。这将停止对值类型的停止装箱。

这仅在被访问的对象没有用于存储的盒子时有用(例如,不存储为对象)。

public static T GetPropertyValue<T>(string propertyIdCode)
{
}

public static int GetPropertyInt(string propertyIdCode)
{
}

答案 8 :(得分:0)

还有另一种方法 - 使用Convert.ChangeType:

CType(Convert.ChangeType(mItem, GetType(TItem)), TItem)