C#:“is”关键字并检查 Not

问题描述 投票:0回答:14

这是一个愚蠢的问题,但您可以使用此代码来检查某些东西是否是特定类型...

if (child is IContainer) { //....

有没有更优雅的方法来检查“NOT”实例?

if (!(child is IContainer)) { //A little ugly... silly, yes I know...

//these don't work :)
if (child !is IContainer) {
if (child isnt IContainer) { 
if (child aint IContainer) { 
if (child isnotafreaking IContainer) { 

是的,是的......愚蠢的问题......

因为对代码的外观存在一些疑问,所以它只是在方法开始处的简单返回。

public void Update(DocumentPart part) {
    part.Update();
    if (!(DocumentPart is IContainer)) { return; }
    foreach(DocumentPart child in ((IContainer)part).Children) {
       //...etc...
c# casting keyword
14个回答
332
投票
if(!(child is IContainer))

是唯一要走的操作员(没有

IsNot
操作员)。

您可以构建一个扩展方法来执行此操作:

public static bool IsA<T>(this object obj) {
    return obj is T;
}

然后用它来:

if (!child.IsA<IContainer>())

你可以遵循你的主题:

public static bool IsNotAFreaking<T>(this object obj) {
    return !(obj is T);
}

if (child.IsNotAFreaking<IContainer>()) { // ...

更新(考虑OP的代码片段):

由于您实际上是在之后转换该值,因此您可以只使用

as
来代替:

public void Update(DocumentPart part) {
    part.Update();
    IContainer containerPart = part as IContainer;
    if(containerPart == null) return;
    foreach(DocumentPart child in containerPart.Children) { // omit the cast.
       //...etc...

117
投票

你可以这样做:

object a = new StreamWriter("c:\\temp\\test.txt");

if (a is TextReader == false)
{
   Console.WriteLine("failed");
}

80
投票

C# 9.0 中的新增功能

https://devblogs.microsoft.com/dotnet/welcome-to-c-9-0/#ological-patterns

if (part is not IContainer)
{
    return;
}

原答案

这个还没有提到。它有效,我认为它看起来比使用

!(child is IContainer)

更好
if (part is IContainer is false)
{
    return;
}

19
投票

C# 9(随 .NET 5 一起发布)包含逻辑模式

and
or
not
,这使我们能够更优雅地编写此内容:

if (child is not IContainer) { ... }

同样,此模式可用于检查 null:

if (child is not null) { ... }

10
投票

为什么不直接使用 else 呢?

if (child is IContainer)
{
  //
}
else
{
  // Do what you want here
}

整洁、熟悉、简单?


10
投票

你的方式很好,但是你可以创建一组扩展方法来“以更优雅的方式检查‘NOT’实例。”

public static bool Is<T>(this object myObject)
{
    return (myObject is T);
}

public static bool IsNot<T>(this object myObject)
{
    return !(myObject is T);
}

然后你可以写:

if (child.IsNot<IContainer>())
{
    // child is not an IContainer
}

5
投票

丑吗?我不同意。唯一的其他方式(我个人认为这是“丑陋”):

var obj = child as IContainer;
if(obj == null)
{
   //child "aint" IContainer
}

3
投票

is
运算符计算结果为布尔值,因此您可以执行任何可以对布尔值执行的操作。要否定它,请使用
!
运算符。为什么你要为此找一个不同的运营商?


3
投票

扩展方法

IsNot<T>
是扩展语法的好方法。请记住

var container = child as IContainer;
if(container != null)
{
  // do something w/ contianer
}

比做类似的事情表现得更好

if(child is IContainer)
{
  var container = child as IContainer;
  // do something w/ container
}

就您而言,这并不重要,因为您是从该方法返回的。换句话说,请注意不要同时进行类型检查和类型转换。


3
投票

虽然这并不能避免括号的问题,但为了人们通过 Google 到达这里,应该提到的是,存在更新的语法(从 C# 7 开始)以使代码的其余部分更加清晰:

if (!(DocumentPart is IContainer container)) { return; }
foreach(DocumentPart child in container.Children) {
    ...

这避免了双重强制转换、空检查以及在可能为空的范围内提供可用变量。


2
投票

虽然 IS 运算符通常是最好的方法,但在某些情况下您可以使用另一种方法。您可以使用 as 运算符并测试 null。

MyClass mc = foo as MyClass;
if ( mc == null ) { }
else {}

0
投票

我偶然发现了这一点,因为添加了

is not
。由于提供的一些答案中使用了泛型,我想也许使用它意味着您甚至可能不需要测试。这将适用于最初的问题,但它不是一个包罗万象的解决方案。对于其他情况,您仍然需要使用
is not

假设您仅将 DocumentPart 指定为

IContainer
类型。

public class  DocumentPart<T> where T : IContainer
{
}

那么更新方法将如下所示

public void Update(DocumentPart<IContainer> part)
{
}

然后,您被迫使用 IContainer 或可转换为 IContainer 的实例(类),例如

public void Update(DocumentPart<ContainerChildOne> part)
{
}

public void Update(DocumentPart<ContainerChildTwo> part)
{
}

如果你想使用IContainer以外的东西,它不会解决基于操作代码中的

do nothing and return
语句,我会像上面那样写。


-2
投票

我就用这个

If(!(对象是汽车)){

}


-3
投票
if (child is IContainer ? false : true)
© www.soinside.com 2019 - 2024. All rights reserved.