是否可以根据给定类型创建ICollection?

时间:2020-01-01 16:45:27

标签: c#

我想创建一个扩展方法,将long类型的ICollection转换为long类型的ICOllection。会是这样的:

    public static void ConvetirLongANullableLong<T, U>(this ICollection<T> paramIcOrigenNoNullable, ICollection<U> paramIcDestinoNullable)
    {
        for (int i = 0; i < paramIcOrigenNoNullable.Count; i++)
        {
            paramIcDestinoNullable.Add((U)paramIcOrigenNoNullable.ElementAt(i));
        }
    }

但是我有一个问题,因为我无法将U转换为T。

这个想法是创建一个通用方法来转换例如长到长?在这种情况下,但是从int到int?或其他任何不可为空的基本类型。

是否有可能为每种类型创建一个方法?

这是由以下帖子所激发的:Fastest way to convert List<int> to List<int?>说,最好使用foreach而不使用linq select或linq cast,因为它比较慢。

谢谢。

PD:我给出V0ldek的答案,因为这是我在这篇文章中真正提出的要求,但是如果我使用linq select(至少在使用Entity Core 3.0时,PavelAnikhouski会如何在其中发表评论)的确更快。我不知道for选项是否在其他版本中更快,因为我指示的链接中的结果与PavelAnikhouski的情况和我自己的情况下的时间差别很大。

3 个答案:

答案 0 :(得分:2)

如果您总是要从T转换为T?,那么就不需要类型U。您知道UU = T?。但是您确实需要约束T进行构造。

public static void ConvertToCollectionOfNullable<T>(
    this ICollection<T> source, 
    ICollection<T?> destination) where T : struct
{
    for (int i = 0; i < source.Count; i++)
    {
        destination.Add(source.ElementAt(i));
    }
}

此外,您可以在集合中使用foreach以获得更干净的代码。

public static void ConvertToCollectionOfNullable<T>(
    this ICollection<T> source,
    ICollection<T?> destination) where T : struct
{
    foreach (var element in source)
    {
        destination.Add(element);
    }
}

答案 1 :(得分:1)

使用OfType<T>中的Cast<T>System.Linq方法,您可以变得更加简单

var list = new List<long>() { 1, 2, 3 };
var converted = list.OfType<long?>().ToList();

OfType<T>不会抛出任何异常,如果强制转换会失败(例如Cast<T>

另一种选择是使用Select方法。由于您知道结果类型,因此cast(编译器也可以帮助您)和装箱也不会有问题

var list = new List<long>() { 1, 2, 3 };
var converted = list.Select(_ => (long?)_).ToList();

答案 2 :(得分:1)

IEnumerable.Cast较慢,因为它使用拳击。这是发生了什么:

long? l = (long?)(object)8; 

但这是将任何内容投射到任何内容的唯一方法。 如果您希望它更快地实现,请针对特定类型。

但是在特殊情况下,如果要将值类型转换为可空类型,则可以坚持使用泛型。您只需要避免处理两种类型(您的<T, U>)是T和T ?,并且必须告诉编译器T是值类型:

  public static IEnumerable<T?> Convert<T>(this IEnumerable<T> list) where T : struct
  {
        return list.Select(x => new T?(x));
  }

如果希望更快,请避免使用LINQ枚举器(避免foreach)并使用简单的循环

    public static IList<T?> Convert<T>(this IList<T> list) where T : struct
    {
        var newlist = new List<T?>(list.Count);
        for (int i = 0; i < list.Count; i++)
            newlist.Add(new T?(list[i]));
        return newlist;
    }