【问题标题】:Choosing return type of collection: Is there a way to return the same type that is provided?选择集合的返回类型:有没有办法返回提供的相同类型?
【发布时间】:2012-11-13 10:16:30
【问题描述】:

在为 API 编写通用扩展方法时,我在选择集合的返回类型时处于两难境地。我已经阅读了关于返回什么集合类型以及应该是什么设计选择的讨论。我一般更喜欢接受最基本的类型作为参数,并返回最丰富的类型。

我现在正在考虑返回与提供的相同类型。无论这是否是一个好的选择,有没有一种方法可以以易于使用的方式完成?

例如。让我有这个:

 public static IEnumerable<T> Generize<T>(this IEnumerable<T> source)
                                         where T : new()
 {
     var lst = source.ToList();
     lst.Add(new T());
     return lst.AsEnumerable(); //since return type is IEnumerable.
 }

现在我想返回 IEnumerableICollectionIList,具体取决于参数 source。所以我稍微修改了一下。

 public static S Generize<S, T>(this S source) where S : IEnumerable<T>
                                               where T : new()
 {
     var lst = source.ToList();
     lst.Add(new T());
     return (S)lst.AsEnumerable(); //not sure if this works
 }

我面临的主要问题是我无法调用函数Generize

var d = new List<int> { 23, 23 };

d.Generize(); //can not find definition and no extension method by the name.....

d.Generize<List<int>, int>(); //works but so ugly..
  1. 正如 Marc 指出的那样,强制转换并非在任何地方都有效。如果S 无论如何是IEnumerable&lt;T&gt;,是否有更好的方法从List&lt;T&gt; 返回S 类型的集合?

  2. 是否可以在不指定类型的情况下自动推断类型?

  3. 还有为什么d.Generize()给出definition not found错误而不是types cannot be inferred错误?

编辑:

虽然IEnumberable&lt;T&gt; 可以是任何具体类型,但在我的情况下,它只会是T[]List&lt;T&gt; 之类的常见类型,或者来自Linq namsespace 的更多类型。处理它们都不容易。只是指出原来的问题现在对我来说没有意义。谢谢大家..!

【问题讨论】:

  • “工作但如此丑陋”只是偶然的工作;如果您使用数组或Collection&lt;T&gt; 尝试它,则会出错
  • @MarcGravell 让我看看。谢谢。
  • @MarcGravell 我不明白你。我尝试使用int[]ICollection&lt;T&gt; 并且它有效..
  • 如果 Sint[],你会得到“无法投射类型为 'System.Collections.Generic.List1[System.Int32]' to type 'System.Int32[]'.". If S` 的对象是 Collection&lt;int&gt;,你会得到”无法投射'System.Collections.Generic.List1[System.Int32]' to type 'System.Collections.ObjectModel.Collection1[System.Int32]' 类型的对象。”。基本上,你用“不确定这是否有效”标记的代码:不。
  • 嗯,我意识到我的问题部分是愚蠢的,因为IEnumerable&lt;T&gt; 可以是任何风格,包括自定义类型。我将尝试自己发布一个处理反思的答案,只是为了回答。

标签: c# generics extension-methods ienumerable type-inference


【解决方案1】:

警告:好吧,我的问题不是很好,我的想法有点愚蠢。这只是为了回答我的帖子,我不推荐它。我将依靠在生产代码中返回正确的List&lt;T&gt;

一种方法是处理几种已知类型的集合类

public static S Generize<S, T>(this S source, T dummyVariable) 
                              where S : class, IEnumerable<T>
{
    var lst = source.ToList();
    lst.Add(dummyVariable);

    if (source is T[])
        return lst.ToArray() as S;

    if (source is List<T>)
        return lst as S;

    if (source is Collection<T>)
        return new Collection<T>(lst) as S;

    throw new TypeAccessException();
}

为了更笼统,我将使用一些反射..

public static S Generize<S, T>(this S source, T dummyVariable) 
                              where S : class, IEnumerable<T>
{
    var lst = source.ToList();
    lst.Add(dummyVariable);

    if (source is Array)
        return lst.ToArray() as S;

    foreach (var c in typeof(S).GetConstructors())
    {
        var p = c.GetParameters();

        if (p.Length != 1)
            continue;

        if (typeof(IEnumerable<T>).IsAssignableFrom(p[0].ParameterType))
            return Activator.CreateInstance(typeof(S), lst) as S;
    }

    throw new TypeAccessException();
}

Question 2 has been answered here 和问题 3 仍然是个谜。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多