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;
}
}