1

We had a discussion today on the job where we were talking about use case where you have code similar to this:

using System;

namespace test
{
    class Program
    {
        public class A
        {
            public void Foo()
            {
                Console.WriteLine("This is A.");
            }
        }

        public class B
        {
            public void Foo()
            {
                Console.WriteLine("This is B");
            }
        }

        public static void Test(object obj)
        {
            if (obj is A a)
            {
                a.Foo();
            }
            else if (obj is B b)
            {
                b.Foo();
            }
        }

        static void Main(string[] args)
        {
            Test(new A());
        }
    }
}

Then we discussed how the "is" keyword can be removed by abstracting the behavior like this (or with an interface, depending on which works best in the context):

using System;

namespace test
{
    class Program
    {
        public abstract class Base
        {
            public abstract void Foo();
        }

        public class A : Base
        {
            public override void Foo()
            {
                Console.WriteLine("This is A.");
            }
        }

        public class B : Base
        {
            public override void Foo()
            {
                Console.WriteLine("This is B");
            }
        }

        public static void Test(Base obj)
        {
            obj.Foo();
        }

        static void Main(string[] args)
        {
            Test(new A());
        }
    }
}

So, from there, we were a bunch of people trying to figure out which would be the scenarios where the use of the "is" keyword would really be justified. All the examples we could come up with were ruled out as they resulted from other code smells..

I did some research on the web for an answer but most websites would only provide definitions and how to use the keyword but I couldn't find any source that I could cite for "good practices" related to the keyword.

In summary, my question is, what are (if any) scenarios where the use of the "is" keyword is justified (necessary/more elegant)?

Edit: More information to clarify. For a lot, if not most keywords/statements/directives, there are context where it makes sense to use it and other contexts where the use is unjustified.

For example, try, catch, throw are great when you need to have a response to an exceptional circumstance that arises while a program is running, such as an attempt to divide by zero. However, most programmers would agree that using them for control flow is a bad idea.

In that same regards, goto can be used in switches or in nested loops and this is generally accepted usage. However, if you start using goto to jump around in the code, this is, again, considered to be a bad idea by most programmers.

Therefore, I want to identify what use cases for is would be accepted and what others would be rejected by most programmer?

DereckM
  • 274
  • 2
  • 11
  • 1
    This is an opinion question, which is, by policy, not a great Stack Overflow question. In general, inheritance (or interface implementation) is a better way to handle this case. However, sometimes, using `is` is a passable solution (it's often when you don't have any control over the types you are handling, and providing a common base type is impossible). If you do choose the `is` route, take a look at the new C# _Pattern Matching Switch_ syntax. It can make for more readable code. – Flydog57 Apr 05 '19 at 23:34

1 Answers1

2

Everything is a code smell to someone, some are more-so than others.

is (C# Reference)

Checks if an object is compatible with a given type, or (starting with C# 7.0) tests an expression against a pattern.

Asking for legitimate uses of is is like asking for legitimate uses of water. It's never ending and all can be debated all day. If you have someone hell-bent on proving everything is a smell, then you will never win.

However, what we know is, if you need to Check if an object is compatible with a given type then you have a legitimate use-case, end of story.

Think about events and the sender parameter.

Think about lists of base types.

<insert oodles of more list items here>

BCL Example

public static IEnumerable<TResult> OfType<TResult>(this IEnumerable source)
{
   if (source == null) throw Error.ArgumentNull("source");
   return OfTypeIterator<TResult>(source);
}

static IEnumerable<TResult> OfTypeIterator<TResult>(IEnumerable source)
{
   foreach (object obj in source)
   {
      if (obj is TResult) yield return (TResult)obj;
   }
}
halfer
  • 19,824
  • 17
  • 99
  • 186
TheGeneral
  • 79,002
  • 9
  • 103
  • 141
  • By that same logic, it would make sense to start using `goto` [goto (C# Reference)](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/goto). "The goto statement transfers the program control directly to a labeled statement." However, it is generally agreed upon that `goto` statements are to be avoided.. – DereckM Apr 05 '19 at 23:42
  • 1
    @DereckM nonsense, even the compiler uses goto, There is a use for everything, if used wisely and its along the code base guidelines you are using. In essence all the guidelines and code smells and patterns and best practices, when all things are equal with performance,fault tolerance, and stable design then it becomes primarily about readability and maintainability – TheGeneral Apr 05 '19 at 23:50
  • 1
    If you use ever exceptions, then you, too, have gotos in your code. Yes, using `is` as a crutch instead of a proper object-oriented design is a bad idea. But that doesn't mean there are no circumstances where its use is indicated. – Cody Gray - on strike Apr 06 '19 at 00:08
  • I agree, but then again, exceptions should _not_ be used as a control flow... otherwise, it is again bad design/bad use of a language directive. And I'm not saying we should ban the use of `is`... I'm just asking for a scenario where it makes the most sense to use it. For example, I can decide to build my application with a control flow through exceptions... that would be horrible but it makes sense to use them to handle exceptional circumstances. In that same way, in what context would it make sense to use "is"? – DereckM Apr 06 '19 at 00:21
  • @DereckM updated from the frame work – TheGeneral Apr 06 '19 at 00:32
  • @DereckM a C# project has not reached it's maturity before there is at least one [goto](https://stackoverflow.com/questions/6545720/does-anyone-still-use-goto-in-c-sharp-and-if-so-why) inside it's code base. :-) – Theodor Zoulias Apr 06 '19 at 01:00