How to create a general method to return a specific type specified in a call?

The following code gives me errors:

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

What do I need to do so that this method returns the type of the variable that 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 a general solution, i.e. I have a class that stores its values โ€‹โ€‹as strings regardless of type, and this general solution just makes the cleaning code:

 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); } } } 
+4
source share
9 answers

It is troublesome; to make the compiler happy, you can double-print, but this implies a window 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 fact, I think you better use the return type of the object .

+13
source

This is an abuse of generics. If you have a small number of types that might be a typical type parameter, just replace it with a lot of methods:

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

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); } 
+2
source

GetPropertyValue<string>("age") wants to return a string. Change it to GetPropertyValue<int>("age") and it will work as long as "age" is your parameter value.

In your implementation, it would be better to get the type of the universal parameter T in order to choose what to return and not base it on the function parameter.

 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()); } } } 
+1
source

You can return the object from GetPropertyValue, and then do the throw. You are trying to use a generic method to return certain types depending on the input parameters. Sounds confusing :-)

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

and then type (int)GetPropertyValue("age");

+1
source

Usually, when you execute a general method, this is a design problem. Usually you want to keep your generic type inside your method ( no castings, no type-based binding ), something like this:

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

On the other hand, if you want to access the properties of an object through their name (it seems that this is what you are doing, sorry if I'm wrong), the correct way would be to use reflection ( PropertyInfo.GetValue ):

 public object GetPropertyValue(object obj, string propertyIdCode) { PropertyInfo pinfo = obj.GetType().GetProperty(propertyIdCode); return pinfo.GetValue(obj, null); } 
+1
source
  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; } 
0
source

The Marc double cast example is the right way to get the compiler to behave properly.

You can write a sperate method for each type of value and have a common method for reference types. This would stop box termination by value types.

This is only useful if access to the objects does not fit into the storage cell (for example, it is not stored as an object).

 public static T GetPropertyValue<T>(string propertyIdCode) { } public static int GetPropertyInt(string propertyIdCode) { } 
0
source

There is another way - using Convert.ChangeType:

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

Source: https://habr.com/ru/post/1299742/


All Articles