我正在尝试为NotOfType
提出一个实现,它有一个可读的调用语法。NotOfType
应该是OfType<T>
的补数,因此会产生所有不属于T
类型的元素
我的目标是实现一个像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>();
但是,我无法提出支持该特定调用语法的实现。
这是我迄今为止所尝试的:
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));
}
}
调用这些方法看起来像这样:
// Animal is inferred
IEnumerable<Animal> fewerAnimals = animals.NotOfType(typeof(Giraffe));
和/或
// Not all types could be inferred, so I have to state all types explicitly
IEnumerable<Animal> fewerAnimals = animals.NotOfType<Animal, Giraffe>();
我认为这两个电话的风格都有很大的缺点。第一个例子有一个多余的“of type/type of”结构,第二个例子没有意义(我想要一个既不是Animals也不是Giraffes的动物列表吗?)).
那么,有没有办法实现我的愿望呢?如果没有,在该语言的未来版本中是否可能?(我在想,也许有一天我们会有命名的类型参数,或者我们只需要显式地提供无法推断的类型参数?)
还是我太傻了
7条答案
按热度按时间rjjhvcjd1#
我不知道你为什么不直接说:
我觉得这是完全可读的。对我来说,它肯定比
animals.NotOfType<Animal, Giraffe>()
更直接,如果我遇到它,我会感到困惑......第一个永远不会让我感到困惑,因为它是立即可读的。如果你想要一个流畅的接口,我想你也可以在
Object
上用一个扩展方法 predicate 来做这样的事情:xnifntxz2#
不如
或者,you can split the generic parameters across two methods:
此外,您还需要决定是否也排除继承类型。
bksxznpy3#
这似乎是一个奇怪的建议,但是在普通的旧
IEnumerable
上使用扩展方法怎么样呢?这将镜像OfType<T>
的签名,并且还将消除冗余<T, TExclude>
类型参数的问题。我还认为,如果您已经有了一个强类型序列,那么就没有什么理由使用特殊的
NotOfType<T>
方法;从一个 arbitrary 类型的序列中排除一个特定的类型似乎更有用(在我看来)……或者让我这么说如果处理的是IEnumerable<T>
,调用Where(x => !(x is T))
是很简单的;在这种情况下,像NotOfType<T>
这样的方法的有用性变得更加可疑。mwg9r5ms4#
我也遇到过类似的问题,在寻找答案的时候遇到了这个问题。
我采用了以下调用语法:
它的缺点是枚举集合两次(因此不能用于无限级数或枚举有副作用的集合,不应该重复),但优点是不需要新的帮助函数,含义很清楚。
在我的实际用例中,我还在
.OfType<Giraffe>()
之后添加了.Where(...)
(长颈鹿也包括在内,除非它们满足只对长颈鹿有意义的特定排除条件)w8ntj3qf5#
如果你要做一个推理的方法,你要一直推理下去。这需要每种类型的示例:
调用者
qlfbtfca6#
我刚试过这个,它的工作原理...
我错过什么了吗?
dffbzjpn7#
你可以考虑一下