选择返回类型的集合:有没有办法返回提供的相同类型?

时间:2012-11-13 10:16:30

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

在编写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.
 }

现在,我想根据参数IEnumerable返回ICollectionIListsource。所以我修改了一下。

 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. 正如马克所指出的那样,铸件无处不在。如果S List<T>S,是否有更好的方法可以从IEnumerable<T>返回d.Generize()类型的集合?

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

  3. 为什么definition not found会出现types cannot be inferred错误而不是IEnumberable<T>错误?

  4. 修改

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

1 个答案:

答案 0 :(得分:0)

警告:好的,我的问题不是很好,我的想法有点愚蠢。这只是回答我的帖子,我不推荐它。我将依赖于在生产代码中返回正确的List<T>

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

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仍然是一个谜。