CA1806: Do not ignore method results

The CA1806 warning is triggered whenever you call a method and ignore the return value. I’ll show examples of a few of the scenarios where you might run into this.

CA1806 – When you call a string method and don’t use the new string

Strings are immutable. Once you create a string, you can’t change it. There are many string methods that appear to modify a string (such as string.Remove), but what they’re really doing is creating a new string object.

When you call these string methods and don’t use the new string they create, you’ll get the CA1806 warning. For example, consider the following code:

string message = "hello";
message.Remove(1);
message.Replace("h", "H");
message.ToUpper();
message.Trim();
message.PadLeft(5);
Code language: C# (cs)

This will generate five CA1806 warnings (one for each string method called). Here’s an example of one of the warnings:

CA1806 Main calls Remove but does not use the new string instance that the method returns. Pass the instance as an argument to another method, assign the instance to a variable, or remove the call if it is unnecessary.

To fix this, set the original string variable to the output of the string method. For example:

string message = "hello";
message = message.Remove(1);
Code language: C# (cs)

This is the most important problem that the CA1806 rule catches. It’s easy to make this mistake because the method names suggest that the string is being modified. So this warning catches this subtle bug. For this reason, you may want to consider treating this warning as an error.

CA1806 – When you call a Linq method without using the results

When you call a Linq method, such as Select(), it doesn’t actually execute until you try to use the results. The execution is deferred.

CA1806 triggers when the Linq method results aren’t set to a variable or used, like this:

string message = "hello";
message.Select(t => char.ToUpper(t));
Code language: C# (cs)

This triggers the following CA1806 warning:

CA1806 ‘Main’ calls ‘Select’ but does not use the value the method returns. Linq methods are known to not have side effects. Use the result in a conditional statement, assign the result to a variable, or pass it as an argument to another method.

CA1806 only partially reveals the underlying problem here. The rule won’t trigger if you set the Linq method call result to a variable, even though you’re not actually using the results:

string message = "hello";
var query = message.Select(t => char.ToUpper(t));
Code language: C# (cs)

Does this solve the underlying problem? No, but it does get rid of the CA1806 warning.

The underlying problem is that the Linq method results aren’t being used. To solve the underlying problem, use the results. For example:

string message = "hello";

var query = message.Select(t => char.ToUpper(t));

foreach(var c in query)
{
	Console.WriteLine(c);
}
Code language: C# (cs)

CA1806 – When you create an instance of an object without saving the reference to a variable

You’ll get the CA1806 warning when you call a constructor without using the created object, like this:

new RaceCar();
Code language: C# (cs)

This will generate the following CA1806 warning:

CA1806 Main creates a new instance of RaceCar which is never used. Pass the instance as an argument to another method, assign the instance to a variable, or remove the object creation if it is unnecessary.

Chances are this is just a simple mistake and you can simply remove this line.

//new RaceCar(); Most likely you'll just want to remove the line
Code language: C# (cs)

Or you can set the object reference to a variable. This will get rid of the CA1806 warning. But it’s unlikely this is the right solution. Why? Because you probably won’t be using this variable anyway, so it’s better to just get rid of the unnecessary constructor call.

var raceCar = new RaceCar();
Code language: JavaScript (javascript)

CA1806 is not triggered by DateTime methods, but it should be

What I don’t like about the CA1806 analyzer rule is that it’s inconsistent.

Just like strings, DateTimes are immutable. Once you create a DateTime object, you can’t change it. And just like with string methods, there are DateTime methods that return a new DateTime object.

It’s easy to make the mistake of thinking these DateTime methods modify the DateTime object. The method names definitely suggest that behavior. But they actually return a new DateTime object with the new value.

For example, consider the following code, which gets the current date/time and adds 1 day to it:

DateTime now = DateTime.Now;
now.AddDays(1);
Code language: C# (cs)

Strangely, the CA1806 warning is not triggered here, even though the new DateTime object returned by AddDays() is being ignored. AddDays() is not modifying the original DateTime object. It’s returning a new DateTime object.

Hopefully one day they’ll extend this CA1806 rule to apply to DateTime, since this would catch this subtle bug just like it does with strings.

Leave a Comment