代码之家  ›  专栏  ›  技术社区  ›  Edward Tanguay

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

  •  4
  • Edward Tanguay  · 技术社区  · 15 年前

    以下代码给出了错误:

    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 回复  |  直到 15 年前
        1
  •  13
  •   Marc Gravell    15 年前

    这很麻烦;为了使编译器满意,您可以双重强制转换,但这意味着值类型有一个框:

        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 返回类型。

        2
  •  4
  •   Eric Lippert    15 年前

    这是对仿制药的滥用。如果泛型类型参数可能包含少量类型,则只需将其替换为这么多方法即可:

    string GetTextProperty(string propertyName) { ... }
    int GetNumberProperty(string propertyName) { ... }
    Giraffe GetGiraffeProperty(string propertyName) { ... }
    
        3
  •  2
  •   Binoj Antony    15 年前

    这应该有用。。。

      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);
      }
    
        4
  •  1
  •   Nick Larsen    15 年前

    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());
            }
        }
    }
    
        5
  •  1
  •   chikak    15 年前

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

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

        6
  •  1
  •   vgru    15 年前

    通常,当您在泛型方法中进行强制转换时,这是一个设计问题。通常,你想保持你的类型 在你的方法里面( ),大致如下:

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

    PropertyInfo.GetValue ):

    public object GetPropertyValue(object obj, string propertyIdCode)
    {
        PropertyInfo pinfo = obj.GetType().GetProperty(propertyIdCode);
        return pinfo.GetValue(obj, null);
    }
    
        7
  •  0
  •   Jamie Ide    15 年前
        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;
        }
    
        8
  •  0
  •   stevehipwell    15 年前

    Marc的双重转换示例是使编译器正确运行的正确方法。

    您可以为每个值类型编写一个sperate方法,并为引用类型编写一个泛型方法。这将停止对值类型进行装箱。

    public static T GetPropertyValue<T>(string propertyIdCode)
    {
    }
    
    public static int GetPropertyInt(string propertyIdCode)
    {
    }
    
        9
  •  0
  •   Mike    10 年前

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