C# 如何实现NotOfType<;T>;在LINQ中,它有一个很好的调用语法?
我正在尝试为C# 如何实现NotOfType<;T>;在LINQ中,它有一个很好的调用语法?,c#,linq,type-inference,code-readability,C#,Linq,Type Inference,Code Readability,我正在尝试为NotOfType设计一个实现,它具有可读的调用语法NOTFTYPE应该是OfType的补充,因此将产生所有非T类型的元素 我的目标是实现一个方法,该方法将被调用,就像类型的一样,就像这段代码的最后一行: public abstract class Animal {} public class Monkey : Animal {} public class Giraffe : Animal {} public class Lion : Animal {} var monkey =
NotOfType
设计一个实现,它具有可读的调用语法NOTFTYPE
应该是OfType
的补充,因此将产生所有非T
类型的元素
我的目标是实现一个方法,该方法将被调用,就像类型的一样,就像这段代码的最后一行:
public abstract class Animal {}
public class Monkey : Animal {}
public class Giraffe : Animal {}
public class Lion : Animal {}
var monkey = new Monkey();
var giraffe = new Giraffe();
var lion = new Lion();
IEnumerable<Animal> animals = new Animal[] { monkey, giraffe, lion };
IEnumerable<Animal> fewerAnimals = animals.NotOfType<Giraffe>();
公共抽象类动物{}
公营猴子:动物{}
公营长颈鹿:动物{}
公营狮子:动物{}
var monkey=newmonkey();
var giraffe=新长颈鹿();
var lion=新lion();
IEnumerable动物=新动物[]{猴子、长颈鹿、狮子};
IEnumerable fewerAnimals=动物。NotOfType();
但是,我无法找到一个支持这种特定调用语法的实现
这就是我迄今为止所尝试的:
public static class EnumerableExtensions
{
public static IEnumerable<T> NotOfType<T>(this IEnumerable<T> sequence, Type type)
{
return sequence.Where(x => x.GetType() != type);
}
public static IEnumerable<T> NotOfType<T, TExclude>(this IEnumerable<T> sequence)
{
return sequence.Where(x => !(x is TExclude));
}
}
公共静态类EnumerableExtensions
{
公共静态IEnumerable NotOfType(此IEnumerable序列,类型类型)
{
返回序列。其中(x=>x.GetType()!=type);
}
公共静态IEnumerable NotOfType(此IEnumerable序列)
{
返回序列。其中(x=>!(x是TExclude));
}
}
调用这些方法如下所示:
// Animal is inferred
IEnumerable<Animal> fewerAnimals = animals.NotOfType(typeof(Giraffe));
//推断出动物
IEnumerable fewerAnimals=动物。NOTFTYPE(typeof(长颈鹿));
及
//并非所有类型都可以推断,因此我必须显式地声明所有类型
IEnumerable fewerAnimals=动物。NotOfType();
我认为这两种电话的风格都有很大的缺陷。第一个是多余的“of type/type of”结构,第二个就是没有意义(我想要一个既不是动物也不是长颈鹿的动物列表吗?)
那么,有没有办法实现我想要的?如果不是的话,在未来的语言版本中可能吗?(我想也许有一天我们会有命名类型参数,或者我们只需要显式地提供无法推断的类型参数?)
还是我太傻了?怎么样
animals.NotOf(typeof(Giraffe));
或者:
animals.NotOf().Type();
公共静态NOTFHOLDER NOTF(此IEnumerable源);
公共类NotOfHolder:iHideObject成员{
公共IEnumerable NotOf();
}
此外,您还需要决定是否也排除继承的类型。这似乎是一个奇怪的建议,但是对于纯旧的
IEnumerable
上的扩展方法呢?这将镜像类型的签名,还将消除冗余的
类型参数的问题
我还认为,如果你已经有了一个强类型序列,那么没有什么理由使用一个特殊的NotOfType
方法;在我看来,从任意类型的序列中排除特定类型似乎更有用。。。或者让我这样说:如果您处理的是一个IEnumerable
,那么调用,其中(x=>!(x是T))
;在这种情况下,像NotOfType
这样的方法的有用性变得更值得怀疑。我不知道你为什么不说:
animals.Where(x => !(x is Giraffe));
这对我来说似乎是完全可读的。对我来说,这肯定比动物。NotOfType()
更直截了当,如果我遇到它,我会感到困惑。。。第一个永远不会让我困惑,因为它可以立即阅读
如果您想要一个流畅的界面,我想您也可以使用对象上的扩展方法谓词执行类似操作:
animals.Where(x => x.NotOfType<Giraffe>())
animals.Where(x=>x.NotOfType())
如果你要建立一种推理方法,你需要一路推理。这需要每种类型的示例:
public static class ExtMethods
{
public static IEnumerable<T> NotOfType<T, U>(this IEnumerable<T> source)
{
return source.Where(t => !(t is U));
}
// helper method for type inference by example
public static IEnumerable<T> NotOfSameType<T, U>(
this IEnumerable<T> source,
U example)
{
return source.NotOfType<T, U>();
}
}
公共静态类ExtMethods
{
公共静态IEnumerable NotOfType(此IEnumerable源)
{
返回源。其中(t=>!(t是U));
}
//通过示例进行类型推断的helper方法
公共静态IEnumerable NotOfSameType(
这是一个数不清的来源,
(举例)
{
返回source.NotOfType();
}
}
叫来
List<ValueType> items = new List<ValueType>() { 1, 1.0m, 1.0 };
IEnumerable<ValueType> result = items.NotOfSameType(2);
List items=newlist(){1,1.0m,1.0};
IEnumerable结果=items.NotOfSameType(2);
我刚刚试过这个,它很管用
public static IEnumerable<TResult> NotOfType<TExclude, TResult>(this IEnumerable<TResult> sequence)
=> sequence.Where(x => !(x is TExclude));
公共静态IEnumerable NotOfType(此IEnumerable序列)
=>序列。其中(x=>!(x是TExclude));
我漏掉了什么东西吗? < P>你可以考虑这个
public static IEnumerable NotOfType<TResult>(this IEnumerable source)
{
Type type = typeof(Type);
foreach (var item in source)
{
if (type != item.GetType())
{
yield return item;
}
}
}
公共静态IEnumerable NotOfType(此IEnumerable源)
{
类型=类型(类型);
foreach(源中的var项)
{
if(type!=item.GetType())
{
收益回报项目;
}
}
}
我有一个类似的问题,在寻找答案时遇到了这个问题
我选择了以下调用语法:
var fewerAnimals = animals.Except(animals.OfType<Giraffe>());
var fewerAnimals=animals.Except(animals.OfType());
它的缺点是枚举集合两次(因此不能与无限级数一起使用),但优点是不需要新的辅助函数,并且意义明确
在我的实际用例中,我也在.OfType()
之后添加了一个.Where(…)
(也包括长颈鹿,除非它们满足特定的排除条件,这对长颈鹿来说是有意义的)我只编写这样的框架/共享代码,如果我觉得它将获得相当数量的重用。您多久需要一次这样的方法?它是否证明了成本(花在思考设计困难上的时间)的合理性?您的两个版本做的事情有很大不同。@Lette:第一个版本也将排除继承类型。@Merlyn:我没有时间,所以没有实际成本。但是是的,这里可能没有太多的重用。现在把它看作是一个实验。我没有用两层以上的继承层次结构测试它,但现在我会。谢谢然而,
public static IEnumerable NotOfType<TResult>(this IEnumerable source)
{
Type type = typeof(Type);
foreach (var item in source)
{
if (type != item.GetType())
{
yield return item;
}
}
}
var fewerAnimals = animals.Except(animals.OfType<Giraffe>());