如何创建一个 c# 方法,该方法将返回与具有不同元素类型的参数相同的集合类型

本文关键字:类型 方法 集合类 元素 参数 集合 创建 何创建 一个 返回 | 更新日期: 2023-09-27 17:56:41

本质上,与这个问题完全相同,但在 C# 中。

我想要这样的东西:

public IList<double> DoSomething(IList<string> strings) {
    //something
}

但我宁愿让它类型化,以便提前知道返回值,这样我就不必强制转换或函数之外的任何内容。我该怎么做?

有没有通用的方法,

public ListType<double> DoSomething<ListType>(ListType<string> strings) where ListType : ???{

设置这个?

如何创建一个 c# 方法,该方法将返回与具有不同元素类型的参数相同的集合类型

C# 不允许你想要的,但最接近的是:

public TList2 DoSomething<TList1, TList2>(TList1 strings) 
    where TList1 : IEnumerable<string>
    where TList2 : ICollection<decimal>, new()
{
    var result = new TList2();
    foreach (var s in strings)
    {
        result.Add(decimal.Parse(s));
    }
    return result;
}

举个例子:

var input = new HashSet<string>(new[] { "1", "2", "3"});
List<decimal> output = DoSomething<HashSet<string>, List<decimal>>(input);

您可以使用 Linq 来执行此操作。

例如,如果您只想解析为双倍,您可以执行以下操作:

List<double> result = strings.Select(double.Parse).ToList()

您可以发送任何其他方法而不是双倍。解析:

List<double> result = strings.Select(DoSomethingWithOneItem).ToList()
double DoSomethingWithOneItem(string item) {
  //your conversion logic
}

不幸的是,例如IList<TInput>IList<TOutput>之间没有关系可以用来帮助这里,因此您需要同时指定输入和输出列表类型,这在一般形式中变得有点麻烦:

IList<string> strings  = new List<string> {"1.1", "2.2", "3.3"};
IList<decimal> result = strings.ConvertToSameListType((Func<string, decimal>)decimal.Parse, () => new List<decimal>());
public static class EnumerableExtensioncGeneralVersion
{
    public static TOutputList ConvertToSameListType<TInputList, TOutputList, TInput, TOutput>(this TInputList source, Func<TInput, TOutput> itemConversion, Func<TOutputList> outputListConstructor)
        where TInputList : IEnumerable<TInput>
        where TOutputList : ICollection<TOutput>
    {
        TOutputList result = outputListConstructor();
        foreach (TOutput convertedItem in source.Select(itemConversion))
        {
            result.Add(convertedItem);
        }
        return result;
    }
}

不过,如果您只为要支持的每种喜欢的集合类型指定一种扩展方法,则可以更好地使用转换:

//Seting up inputs
IList<string> strings  = new List<string> {"1.1", "2.2", "3.3"};
IEnumerable<string> enumerableStrings = strings.Select(x => x);
ObservableCollection<string> observableStrings = new ObservableCollection<string>(strings);
//Converting
IList<decimal> resultList = strings.Convert(decimal.Parse);
IEnumerable<decimal> resultEnumerable = enumerableStrings.Convert(decimal.Parse);
ObservableCollection<decimal> observableResult = observableStrings.Convert(decimal.Parse);
public static class EnumerableExtensions
{
    public static IList<TOutput> Convert<TInput, TOutput>(this IList<TInput> source, Func<TInput, TOutput> itemConversion)
    {
        return source.Select(itemConversion).ToList();
    }
    public static IEnumerable<TOutput> Convert<TInput, TOutput>(this IEnumerable<TInput> source, Func<TInput, TOutput> itemConversion)
    {
        return source.Select(itemConversion);
    }
    public static ObservableCollection<TOutput> Convert<TInput, TOutput>(this ObservableCollection<TInput> source, Func<TInput, TOutput> itemConversion)
    {
        return new ObservableCollection<TOutput>(source.Select(itemConversion));
    }
}