Следующий код дает мне ошибки:
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);
}
}
}
, который является неприятным; Чтобы сделать компилятор счастливым, вы можете дважды отличить, но это подразумевает коробку для типов значений:
public static T GetPropertyValue<T>(string propertyIdCode)
{
if (propertyIdCode == "firstName")
return (T)(object)"Jim";
if (propertyIdCode == "age")
return (T)(object)32;
return default(T);
}
На самом деле, я думаю, вы можете быть лучше, просто используя объект
Тип возврата.
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;
}
Пример двойного литья MARC является правильным способом, чтобы сделать компилятор, чтобы вести себя правильно.
Вы можете написать спетель для каждого типа значения и иметь универсальный метод для контрольных типов. Это прекратит остановить бокс на типов значений.
Это полезно только в том случае, если доступ к объектам не входит в систему для хранения (например, не сохраняется как объект).
public static T GetPropertyValue<T>(string propertyIdCode)
{
}
public static int GetPropertyInt(string propertyIdCode)
{
}
Это должно работать ...
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);
}
Это злоупотребление дженериками. Если у вас есть небольшое количество типов, что параметр «Общий тип» может быть, просто заменить его с помощью многих способов:
string GetTextProperty(string propertyName) { ... }
int GetNumberProperty(string propertyName) { ... }
Giraffe GetGiraffeProperty(string propertyName) { ... }
Обычно, когда вы отличаете в общий метод, это проблема дизайна. Обычно вы хотите сохранить свой тип в вашем методе внутри вашего метода ( без литья, без пробки на основе типа ), что-то подобное:
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);
}
GetPropertyValue
хочет вернуть строку. Измените его на GetPropertyValue
, и он будет работать до тех пор, пока «возраст» - это ваше значение параметра.
Ваша реализация будет лучше получить тип универсального параметра 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());
}
}
}
Вы можете вернуть объект из GetPropertyValue, а затем сделать актеры. Вы пытаетесь использовать универсальный метод для возврата определенных типов в зависимости от входных параметров. Звучит с толку: -)
public static object GetPropertyValue(string propertyIdCode)
{
if (propertyIdCode == "firstName")
return "Jim";
if (propertyIdCode == "age")
return 32;
return null;
}
, а затем набрал (INT) GetPropertyValue («возраст»);