Impure method called for readonly field

I am using Visual Studio 2010 + Resharper and it shows a warning with the following code:

if (rect.Contains(point)) { ... } 

rect is the readonly Rectangle field, and Resharper shows me this warning:

"The Impure method is called for the readonly field of type value."

What are unclean methods and why is this warning shown to me?

+68
c # resharper
Mar 29 2018-12-12T00:
source share
5 answers

First, the answers of John, Michael, and Jared are mostly correct, but I have a few more things that I would like to add to them.

What is meant by the "unclean" method?

It’s easier to characterize clean methods. The "pure" method has the following characteristics:

  • His conclusion is completely determined by his input; its output does not depend on external factors, such as time of day or bit on the hard drive. His exit does not depend on his story; calling the method with the given argument twice should give the same result.
  • The pure method does not produce observed mutations in the world around it. A pure method may choose to mutate a particular state for efficiency, but a pure method, say, does not change the field of its argument.

For example, Math.Cos is a clean method. Its output depends only on its input, and the input does not change when called.

The impure method is a method that is not pure.

What are some of the dangers of passing readonly structures to unclean methods?

There are two that come to mind. The first is the one that John, Michael, and Jared pointed out, and this is the one that Reshar warns you about. When you call a method in a struct, we always pass a reference to the variable that is the recipient in case the method wants to change this variable.

So what if you call such a method by value and not by variable? In this case, we create a temporary variable, copy the value into it and pass the link to the variable.

The readonly variable is considered a value because it cannot be changed outside of the constructor. Thus, we copy the variable to another variable, and an unclean method may mutate the copy when you intend to change it.

This is the danger of transmitting the readonly structure as a receiver. There is also the danger of passing a structure containing a readonly field. A structure containing a readonly field is common practice, but it is basically written to verify that the type system has no cash; The read-only of a specific variable is determined by the owner of the repository. An instance of a reference type "owns" its own store, but an instance of a type does not!

 struct S { private readonly int x; public S(int x) { this.x = x; } public void Badness(ref S s) { Console.WriteLine(this.x); s = new S(this.x + 1); // This should be the same, right? Console.WriteLine(this.x); } } 

Someone thinks that this.x will not change, because x is a read-only field, and Badness not a constructor. But...

 S s = new S(1); s.Badness(ref s); 

... clearly demonstrates the falsity of this. this and s refer to the same variable, and this variable is not readonly!

+79
Mar 29 2018-12-12T00:
source share

An unclean method is one that does not guarantee that the value will remain as it was.

In .NET 4, you can decorate methods and types [Pure] to declare them clean, and R # will pay attention to this. Unfortunately, you cannot apply it to other members, and you cannot convince R # that the type / member is pure in a .NET 3.5 project, as far as I know. (This will constantly bite me at Noda Time .)

The idea is that if you call a method that modifies a variable, but you call it in a read-only field, it probably does not do what you want, so R # will warn you about it. For example:

 public struct Nasty { public int value; public void SetValue() { value = 10; } } class Test { static readonly Nasty first; static Nasty second; static void Main() { first.SetValue(); second.SetValue(); Console.WriteLine(first.value); // 0 Console.WriteLine(second.value); // 10 } } 

This would be a really useful warning if every method that was actually clean were declared this way. Unfortunately, this is not so, therefore there are many false positives: (

+45
Mar 29 2018-12-12T00:
source share

The short answer is that it is a false positive, and you can safely ignore this warning.

The longer answer is that accessing the read-only value type creates a copy of it, so that any changes to the value made by the method will only affect the copy. ReSharper does not understand that Contains is a pure method (this means that it has no side effects). Eric Lippert talks about it here: Readonly Structs mutation

+13
Mar 29 2018-12-12T00:
source share

It seems that Reshaprer believes that the Contains method can change the value of rect . Because rect is a readonly struct , the C # compiler makes protective copies of the value to prevent the method from changing in the readonly field. Essentially, the last code is as follows:

 Rectangle temp = rect; if (temp.Contains(point)) { ... } 

Resharper warns you that Contains can mutate rect in a way that would be immediately lost, because it happened temporarily.

+11
Mar 29 '12 at 2:35
source share

An unclean method is a method that can have side effects. In this case, Resharper seems to be able to change rect . This is probably not the case, but the chain of evidence is broken.

+5
Mar 29 2018-12-12T00:
source share



All Articles