Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何实现NotOfType<;T>;在LINQ中,它有一个很好的调用语法?_C#_Linq_Type Inference_Code Readability - Fatal编程技术网

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>());