C# IEnumerable<;T>;。单件和铸造

C# IEnumerable<;T>;。单件和铸造,c#,c#-4.0,C#,C# 4.0,I a有两个对象a和B。B继承自a并具有更多属性。 我有只包含B对象的IEnumerable{A}。 我想做的是: list.Single(b => b.PropertyThatOnlyExistOnB == "something") 我希望这样的事情能奏效: list.Single((B) b => b.PropertyThatOnlyExistOnB == "something") 但它没有编译。现在我只是在做: B result = null; foreach (b in

I a有两个对象a和B。B继承自a并具有更多属性。 我有只包含B对象的IEnumerable{A}。 我想做的是:

list.Single(b => b.PropertyThatOnlyExistOnB == "something")
我希望这样的事情能奏效:

list.Single((B) b => b.PropertyThatOnlyExistOnB == "something")
但它没有编译。现在我只是在做:

B result = null;
foreach (b in list)
{
     if((B)b.PropertyThatOnlyExistOnB == "something")
     {
      result = (B)b;
     }
}
有较短的路吗? 谢谢

使用扩展方法进行筛选/转换

list.OfType<B>().Single(b => b.PropertyThatOnlyExistOnB == "something")
list.OfType()
使用扩展方法进行筛选/转换

list.OfType<B>().Single(b => b.PropertyThatOnlyExistOnB == "something")
list.OfType()

尽管我最喜欢@VirtualBlackBox的答案,但为了完整起见:以下是如何让您的想法发挥作用:

list.Single(b => ((B)b).PropertyThatOnlyExistOnB == "something");
你并没有偏离正轨那么远,只是你把一些语法弄糊涂了。
b=>表达式
语法表示lambda表达式。除非要添加(或删除)参数,否则无法在
=>
之前开始更改内容:

* `x => LAMBDA_WITH_ONE_PARAMETER`
* `(x) => LAMBDA_WITH_ONE_PARAMETER`
* `() => LAMBDA_WITH_NO_PARAMETERS`
* `(x, y, z) => LAMBDA_WITH_THREE_PARAMETERS`

尽管我最喜欢@VirtualBlackBox的答案,但为了完整起见:以下是如何让您的想法发挥作用:

list.Single(b => ((B)b).PropertyThatOnlyExistOnB == "something");
你并没有偏离正轨那么远,只是你把一些语法弄糊涂了。
b=>表达式
语法表示lambda表达式。除非要添加(或删除)参数,否则无法在
=>
之前开始更改内容:

* `x => LAMBDA_WITH_ONE_PARAMETER`
* `(x) => LAMBDA_WITH_ONE_PARAMETER`
* `() => LAMBDA_WITH_NO_PARAMETERS`
* `(x, y, z) => LAMBDA_WITH_THREE_PARAMETERS`
这应该很好:

list.Single<A>(b => (b as B).PropertyThatOnlyExistOnB == "something")
list.Single(b=>(b作为b.propertythonlyexistonb==“某物”)
如果您不想冒抛出异常的风险,可以这样做:

list.Single<A>(b => ((b is B)&&((b as B).PropertyThatOnlyExistOnB == "something")))
list.Single(b=>((b是b)和((b作为b.propertythonlyexistonb==“某物”))
这应该可以正常工作:

list.Single<A>(b => (b as B).PropertyThatOnlyExistOnB == "something")
list.Single(b=>(b作为b.propertythonlyexistonb==“某物”)
如果您不想冒抛出异常的风险,可以这样做:

list.Single<A>(b => ((b is B)&&((b as B).PropertyThatOnlyExistOnB == "something")))
list.Single(b=>((b是b)和((b作为b.propertythonlyexistonb==“某物”))
我有只包含B个对象的
IEnumerable

我会质疑关于变量的这句话。您已指定它是一个
IEnumerable
,但它只包含
B
的实例。这样做的目的是什么?如果您在所有情况下都明确只需要
B
的实例,那么最好将其设置为
IEnumerable
,因为它可以保护编译时可能发现的问题

考虑以下情况,我认为您可能有一些类似的代码:

var setOfA = // Get a set of A.
DoSomethingWithA(setOfA);

var instanceOfB = GetInstanceOfB(setOfA);
list.Cast<B>().Single(b => b.PropertyThatOnlyExistOnB == "something");
在这种情况下,我可以理解,
IEnumerable
是完全有效的,除非您想要执行后一个操作,
GetInstanceOfB
。让我们想象一下,定义是:

B GetInstanceOfB(IEnumerable<A> setOfA)
{
    return // The answer to your question.
}
如果
setOfA
实际上是:
[cbb]
呢。您可以看到显式强制转换
(B)B
将导致引发
InvalidCastException
。由于
单个
操作的性质,它将继续枚举,直到第一个实例中某个谓词失败(
propertythonlyexistonb==“something”
),或者引发异常。在本例中,可能会引发异常,这是意外的,并且可能未经处理。这个答案类似于:

var setOfA = // Get a set of A.
DoSomethingWithA(setOfA);

var instanceOfB = GetInstanceOfB(setOfA);
list.Cast<B>().Single(b => b.PropertyThatOnlyExistOnB == "something");
这允许您安全地键入cast到实际上是
B
a
的潜在子集,并且编译器可以保证谓词仅在
IEnumerable
上使用

但这会让我发现,代码中的连接点正试图处理
IEnumerable
,但在真正需要
IEnumerable
的地方执行操作。在这种情况下,您不应该重构此代码,使其可能具有显式方法:

B GetMatchingInstanceOfB(IEnumerable<B> setOfB)
{
    if (setOfB == null) throw new ArgumentNullException("setOfB");

    return setOfB.Single(b => b.PropertyThatOnlyExistOnB == "something");
}
我还假设在所有实例都是
B
,谓词将失败的情况下,您有足够的错误处理,例如,超过1项满足
属性AtonlyExistonB==“something”

这可能是一个关于检查代码的毫无意义的咆哮,但我认为值得考虑可能出现的意外情况,以及如何潜在地调整变量可以在将来为您节省潜在的麻烦

我有只包含B个对象的
IEnumerable

我会质疑关于变量的这句话。您已指定它是一个
IEnumerable
,但它只包含
B
的实例。这样做的目的是什么?如果您在所有情况下都明确只需要
B
的实例,那么最好将其设置为
IEnumerable
,因为它可以保护编译时可能发现的问题

考虑以下情况,我认为您可能有一些类似的代码:

var setOfA = // Get a set of A.
DoSomethingWithA(setOfA);

var instanceOfB = GetInstanceOfB(setOfA);
list.Cast<B>().Single(b => b.PropertyThatOnlyExistOnB == "something");
在这种情况下,我可以理解,
IEnumerable
是完全有效的,除非您想要执行后一个操作,
GetInstanceOfB
。让我们想象一下,定义是:

B GetInstanceOfB(IEnumerable<A> setOfA)
{
    return // The answer to your question.
}
如果
setOfA
实际上是:
[cbb]
呢。您可以看到显式强制转换
(B)B
将导致引发
InvalidCastException
。由于
单个
操作的性质,它将继续枚举,直到第一个实例中某个谓词失败(
propertythonlyexistonb==“something”
),或者引发异常。在本例中,可能会引发异常,这是意外的,并且可能未经处理。这个答案类似于:

var setOfA = // Get a set of A.
DoSomethingWithA(setOfA);

var instanceOfB = GetInstanceOfB(setOfA);
list.Cast<B>().Single(b => b.PropertyThatOnlyExistOnB == "something");
这允许您安全地键入cast到实际上是
B
a
的潜在子集,并且编译器可以保证谓词仅在
IEnumerable
上使用

但这会让我发现,代码中的连接点正试图处理
IEnumerable
,但在真正需要
IEnumerable
的地方执行操作。在这种情况下,我们不应该