C# 什么是强类型泛型函数返回的适当方法?

C# 什么是强类型泛型函数返回的适当方法?,c#,generics,C#,Generics,我正在编写一个过滤器函数,以返回从更大的超类型集合(例如对象)中指定的特定类型。我的想法是给你一个可枚举的,然后你返回给我所有的字符串。您可以这样编写,而无需使用泛型: public static IEnumerable Filter(IEnumerable source, Type type) { List<object> results = new List<object>(); foreach(object o in source) {

我正在编写一个过滤器函数,以返回从更大的超类型集合(例如对象)中指定的特定类型。我的想法是给你一个可枚举的,然后你返回给我所有的字符串。您可以这样编写,而无需使用泛型:

public static IEnumerable Filter(IEnumerable source, Type type)
{
    List<object> results = new List<object>();

    foreach(object o in source)
    {
        if(o != null && o.GetType() == type)
        {
            results.Add(o);
        }
    }

    return results;
}
其中,作为最终版本,将使用类型说明符调用:

Filter<string>(myList);
过滤器(myList);
如果返回类型不会自动隐含在签名中,那么强类型泛型函数的返回的合适方式是什么?(为什么?)


(编辑说明:我们的输入不是类型化的,例如IEnumerable。充其量只能是IEnumerable。此函数从其他类型的整个集合中返回Ts。)

Linq中包含的以下扩展方法正是您需要的:

IEnumerable<T> OfType<T>(this IEnumerable enumerable);
IEnumerable类型(此IEnumerable可枚举);
下面是一个使用示例:

List<object> objects = //...

foreach(string str in objects.OfType<string>())
{
    //...
}
列出对象=/。。。
foreach(objects.OfType()中的字符串str)
{
//...
}

如您所见,他们使用泛型参数作为返回类型说明符。这比使用类型或字符串并返回非类型安全枚举更简单、更安全。

最干净的方法是

public static IEnumerable<T> Filter<T>(IEnumerable<T> source)
公共静态IEnumerable筛选器(IEnumerable源)
这将删除所有非类型安全函数。然后,您可以通过cast调用将任何非泛型IEnumerable转换为泛型版本

IEnumerable enumerable = GetMyEnumerable();
var filtered = Filter(enumerable.Cast<string>());
IEnumerable enumerable=GetMyEnumerable();
var filtered=Filter(enumerable.Cast());
此外,还可以将其作为扩展方法,使调用更加精简

public static IEnumerable<T> Filter<T>(this IEnumerable<T> source)
...
var filtered = GetMyEnumerable().Cast<string>().Filter();
公共静态IEnumerable筛选器(此IEnumerable源)
...
var filtered=GetMyEnumerable().Cast().Filter();
编辑

OP提到他们只想过滤到特定的类型。在这种情况下,您可以只使用Enumerable.OfType

var filtered = GetMyEnumerable().OfType<SomeType>();
var filtered=GetMyEnumerable().OfType();

我通常更喜欢最终版本-它指定了所有相关信息,而没有其他内容。给定带有参数的版本,如果您对代码不熟悉,您不希望参数的值有意义,而不仅仅是类型吗


这种“虚拟参数”模式有时很有用,但我通常会避开它——或者至少提供一个不需要的重载。

这是我的2美分。我对你要过滤的内容有点困惑。IEnumerable是非泛型的,因此如何过滤非泛型源并返回IEnumerable的结果

我认为最干净的是

public static IEnumerable<T> Filter<T>(IEnumerable<T> source)
公共静态IEnumerable筛选器(IEnumerable源)
如果您知道T的过滤器将是什么类型的,您甚至可以进行泛型类型检查,例如,只有某个接口或基类的类或对象,或值类型..诸如此类

public static IEnumerable<T> Filter<T>(IEnumerable<T> source) where T : class
public static IEnumerable<T> Filter<T>(IEnumerable<T> source) where T : struct
公共静态IEnumerable筛选器(IEnumerable源代码),其中T:class
公共静态IEnumerable筛选器(IEnumerable源),其中T:struct

如果您使用的是框架3.5,那么它已经在IEnumerable中实现了:

IEnumerable<string> s = someList.OfType<string>()
IEnumerable s=someList.OfType()
很明显(至少对我来说)您想要的是最终版本:

IEnumerable<T> Filter<T>(IEnumerable source)
IEnumerable筛选器(IEnumerable源)
通过还原的过程,如果没有别的

第一版:

IEnumerable<T> Filter<T>(IEnumerable source, Type type)
IEnumerable筛选器(IEnumerable源,类型)
必须处理我传入的与约束不匹配的类型的疯狂:

第二个版本:

IEnumerable<T> Filter<T>(IEnumerable source, T type)
IEnumerable筛选器(IEnumerable源,T类型)
让我构造了一个示例,它可能很昂贵,或者无法用于构造。另外,如果我传入null(在任何一种情况下)会怎么样


另一方面,对于单个约束,我认为类型参数应该是T。如果TResult是类似于Func的函数的返回,那么您可以不使用它,但否则它只是更多地键入而不那么清晰。

我认为这正是您想要的

public static IEnumerable<T> OfType<T>(IEnumerable source) {
    foreach (object obj in source)
        if (obj is T)
            yield return (T)obj;
}
类型的公共静态IEnumerable(IEnumerable源){
foreach(源中的对象obj)
if(obj是T)
收益率(T)obj;
}
稍微复杂一点但(可能)稍微快一点的版本会更好

public static IEnumerable<T> OfType<T>(IEnumerable source) {
    foreach (object obj in source) {
        T result = obj as T;
        if (result != null)
            yield return result;
    }
}
类型的公共静态IEnumerable(IEnumerable源){
foreach(源中的对象obj){
T结果=obj作为T;
如果(结果!=null)
收益结果;
}
}

您忘记了“this”关键字-为您修复了它。@Joel谢谢!我甚至专门添加了两次,以将其添加到中并显示差异。我将更新第一篇文章,使其更加清晰,但我们正在处理混乱类型的枚举。我充其量是数不清的。我们正在筛选到枚举中的Ts。感谢更新。OfType是一个Linq扩展方法。不幸的是,我们使用的是2.0,所以我们很幸运有泛型。另一篇文章提到了这一点,MS标准似乎是指定类型。因此“.net”方式似乎是指定类型,这很好,谢谢。不幸的是,我们处在一个2.0的世界,我们很幸运有了泛型。是的,我理解,我们在2.0上也被困了很长一段时间。我想最接近.Net的是你最后的解决方案。唯一缺少的是扩展方法。我更新了第一篇文章,使其更加清晰。我正在从一组对象中取出Ts。充其量它在输入端是IEnumerable的。你无法从中推断出回报,因此提出了这个问题。乔恩,谢谢你口头回答这个哲学问题!如果我能将两个答案标记为“已接受”,这将是第二个。另一个引用了LINQ中的MS代码,这更具权威性,但我也很感谢大家的讨论!谢谢。使用为并保存重复的演员阵容:
IEnumerable<T> Filter<T>(IEnumerable source, Type type)
IEnumerable<T> Filter<T>(IEnumerable source, T type)
public static IEnumerable<T> OfType<T>(IEnumerable source) {
    foreach (object obj in source)
        if (obj is T)
            yield return (T)obj;
}
public static IEnumerable<T> OfType<T>(IEnumerable source) {
    foreach (object obj in source) {
        T result = obj as T;
        if (result != null)
            yield return result;
    }
}