hugoware
hugoware

Reputation: 36407

C# : 'is' keyword and checking for Not

This is a silly question, but you can use this code to check if something is a particular type...

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

Is there a more elegant way to check for the "NOT" instance?

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) { 

Yes, yes... silly question....

Because there is some question on what the code looks like, it's just a simple return at the start of a method.

public void Update(DocumentPart part) {
    part.Update();
    if (!(DocumentPart is IContainer)) { return; }
    foreach(DocumentPart child in ((IContainer)part).Children) {
       //...etc...

Upvotes: 328

Views: 154047

Answers (14)

Mukus
Mukus

Reputation: 5033

I stumbled upon this seeing as is not had been added. Since generics is used in a some of the answers provided, I thought maybe the use of it means you may not even need to test. This will work for the original problem but it is not an all encompassing solution. You will still need to use is not for other situations.

Say you specify DocumentPart as being of type IContainer only.

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

Then the update method will look like below

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

You're then forced to use IContainer or an instance(of class) that is covertible to IContainer like

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

or

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

It won't solve for if you want to use something other than IContainer Based on the do nothing and return statement in the op's code, I would write it like above.

Upvotes: 0

Todd Skelton
Todd Skelton

Reputation: 7239

New In C# 9.0

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

if (part is not IContainer)
{
    return;
}

Original Answer

This hasn't been mentioned yet. It works and I think it looks better than using !(child is IContainer)

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

Upvotes: 93

Ill use this

If(!(object is Car)){

}

Upvotes: -2

Thorkil Holm-Jacobsen
Thorkil Holm-Jacobsen

Reputation: 7686

C# 9 (released with .NET 5) includes the logical patterns and, or and not, which allows us to write this more elegantly:

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

Likewise, this pattern can be used to check for null:

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

Upvotes: 23

StriplingWarrior
StriplingWarrior

Reputation: 156728

While this doesn't avoid the problem of parentheses, for the sake of people getting here via Google, it should be mentioned that newer syntax exists (as of C# 7) to make the rest of your code a little cleaner:

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

This avoids the double-cast, the null-check, and having a variable available in scopes where it could be null.

Upvotes: 3

Robert Cartaino
Robert Cartaino

Reputation: 28142

The way you have it is fine but you could create a set of extension methods to make "a more elegant way to check for the 'NOT' instance."

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

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

Then you could write:

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

Upvotes: 11

Ternary
Ternary

Reputation: 3

if (child is IContainer ? false : true)

Upvotes: -3

Mehrdad Afshari
Mehrdad Afshari

Reputation: 422270

if(!(child is IContainer))

is the only operator to go (there's no IsNot operator).

You can build an extension method that does it:

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

and then use it to:

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

And you could follow on your theme:

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

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

Update (considering the OP's code snippet):

Since you're actually casting the value afterward, you could just use as instead:

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...

Upvotes: 336

Jeff
Jeff

Reputation: 561

The extension method IsNot<T> is a nice way to extend the syntax. Keep in mind

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

performs better than doing something like

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

In your case, it doesn't matter as you are returning from the method. In other words, be careful to not do both the check for type and then the type conversion immediately after.

Upvotes: 3

cjk
cjk

Reputation: 46475

You can do it this way:

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

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

Upvotes: 118

Brian Rasmussen
Brian Rasmussen

Reputation: 116481

The is operator evaluates to a boolean result, so you can do anything you would otherwise be able to do on a bool. To negate it use the ! operator. Why would you want to have a different operator just for this?

Upvotes: 3

Muad&#39;Dib
Muad&#39;Dib

Reputation: 29276

While the IS operator is normally the best way, there is an alternative that you can use in some cirumstances. You can use the as operator and test for null.

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

Upvotes: 2

BFree
BFree

Reputation: 103770

Ugly? I disagree. The only other way (I personally think this is "uglier"):

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

Upvotes: 5

Mark Broadhurst
Mark Broadhurst

Reputation: 2695

Why not just use the else ?

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

Its neat it familiar and simple ?

Upvotes: 10

Related Questions