C# 如何使方法的返回类型通用?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9808035/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-09 10:41:36  来源:igfitidea点击:

How do I make the return type of a method generic?

c#.netgenericsreturn-type

提问by MacGyver

Is there a way to make this method generic so I can return a string, bool, int, or double? Right now, it's returning a string, but if it's able find "true" or "false" as the configuration value, I'd like to return a bool for example.

有没有办法让这个方法通用,这样我就可以返回一个字符串、布尔值、整数或双精度值?现在,它返回一个字符串,但如果它能够找到“true”或“false”作为配置值,我想返回一个布尔值。

    public static string ConfigSetting(string settingName)
    {  
         return ConfigurationManager.AppSettings[settingName];
    }

采纳答案by Jon Skeet

You need to make it a generic method, like this:

您需要使其成为通用方法,如下所示:

public static T ConfigSetting<T>(string settingName)
{  
    return /* code to convert the setting to T... */
}

But the callerwill have to specify the type they expect. You could then potentially use Convert.ChangeType, assuming that all the relevant types are supported:

但是调用者必须指定他们期望的类型。Convert.ChangeType假设支持所有相关类型,您就可以潜在地使用:

public static T ConfigSetting<T>(string settingName)
{  
    object value = ConfigurationManager.AppSettings[settingName];
    return (T) Convert.ChangeType(value, typeof(T));
}

I'm not entirely convinced that all this is a good idea, mind you...

我并不完全相信这一切都是个好主意,请注意...

回答by BrokenGlass

You could use Convert.ChangeType():

你可以使用Convert.ChangeType()

public static T ConfigSetting<T>(string settingName)
{
    return (T)Convert.ChangeType(ConfigurationManager.AppSettings[settingName], typeof(T));
}

回答by Adam Howard

 private static T[] prepareArray<T>(T[] arrayToCopy, T value)
    {
        Array.Copy(arrayToCopy, 1, arrayToCopy, 0, arrayToCopy.Length - 1);
        arrayToCopy[arrayToCopy.Length - 1] = value;
        return (T[])arrayToCopy;
    }

I was performing this throughout my code and wanted a way to put it into a method. I wanted to share this here because I didn't have to use the Convert.ChangeType for my return value. This may not be a best practice but it worked for me. This method takes in an array of generic type and a value to add to the end of the array. The array is then copied with the first value stripped and the value taken into the method is added to the end of the array. The last thing is that I return the generic array.

我在整个代码中都在执行此操作,并且想要一种将其放入方法中的方法。我想在这里分享这个,因为我不必使用 Convert.ChangeType 作为我的返回值。这可能不是最佳实践,但对我有用。此方法接受一个泛型类型的数组和一个要添加到数组末尾的值。然后复制数组并删除第一个值,并将方法中采用的值添加到数组的末尾。最后一件事是我返回通用数组。

回答by RollerCosta

There are many ways of doing this(listed by priority, specific to the OP's problem)

有很多方法可以做到这一点(按优先级列出,特定于 OP 的问题)

  1. Option 1: Straight approach- Create multiple functions for each type you expect rather than having one generic function.

    public static bool ConfigSettingInt(string settingName)
    {  
         return Convert.ToBoolean(ConfigurationManager.AppSettings[settingName]);
    }
    
  2. Option 2: When you don't want to use fancy methods of conversion- Cast the value to object and then to generic type.

    public static T ConfigSetting<T>(string settingName)
    {  
         return (T)(object)ConfigurationManager.AppSettings[settingName];
    }
    

    Note -This will throw an error if the cast is not valid(your case). I would not recommend doing this if you are not sure about the type casting, rather go for option 3.

  3. Option 3: Generic with type safety- Create a generic function to handle type conversion.

    public static T ConvertValue<T,U>(U value) where U : IConvertible
    {
        return (T)Convert.ChangeType(value, typeof(T));
    } 
    

    Note -T is the expected type, note the where constraint here(type of U must be IConvertible to save us from the errors)

  1. 选项 1:直接方法- 为您期望的每种类型创建多个函数,而不是拥有一个通用函数。

    public static bool ConfigSettingInt(string settingName)
    {  
         return Convert.ToBoolean(ConfigurationManager.AppSettings[settingName]);
    }
    
  2. 选项 2:当您不想使用花哨的转换方法时- 将值转换为对象,然后转换为泛型类型。

    public static T ConfigSetting<T>(string settingName)
    {  
         return (T)(object)ConfigurationManager.AppSettings[settingName];
    }
    

    注意 -如果转换无效(您的情况),这将引发错误。如果您不确定类型转换,我不建议这样做,而是选择选项 3。

  3. 选项 3:具有类型安全性的泛型 - 创建一个泛型函数来处理类型转换。

    public static T ConvertValue<T,U>(U value) where U : IConvertible
    {
        return (T)Convert.ChangeType(value, typeof(T));
    } 
    

    注意 -T 是预期的类型,注意这里的 where 约束(U 的类型必须是 IConvertible 以防止我们出现错误)

回答by Vinay Chanumolu

You have to convert the type of your return value of the method to the Generic type which you pass to the method during calling.

您必须将方法的返回值类型转换为在调用期间传递给方法的通用类型。

    public static T values<T>()
    {
        Random random = new Random();
        int number = random.Next(1, 4);
        return (T)Convert.ChangeType(number, typeof(T));
    }

You need pass a type that is type casteable for the value you return through that method.

您需要为通过该方法返回的值传递一个类型可转换的类型。

If you would want to return a value which is not type casteable to the generic type you pass, you might have to alter the code or make sure you pass a type that is casteable for the return value of method. So, this approach is not reccomended.

如果您想返回一个不可类型转换的值到您传递的泛型类型,您可能需要更改代码或确保您传递的类型对于方法的返回值是可转换的。所以,不推荐这种方法。

回答by Prabhakar

Create a function and pass out put parameter as of generic type.

创建一个函数并将 put 参数作为泛型类型传递。

 public static T some_function<T>(T out_put_object /*declare as Output object*/)
    {
        return out_put_object;
    }

回答by Sid

Please try below code :

请尝试以下代码:

public T? GetParsedOrDefaultValue<T>(string valueToParse) where T : struct, IComparable
{
 if(string.EmptyOrNull(valueToParse))return null;
  try
  {
     // return parsed value
     return (T) Convert.ChangeType(valueToParse, typeof(T));
  }
  catch(Exception)
  {
   //default as null value
   return null;
  }
 return null;
}