Why is this method unclean?

I read this answer: stack overflow

But I obviously don’t understand this, because I can’t understand why my method is unclean. (This method matters ToExactLocation()).

public struct ScreenLocation
{
    public ScreenLocation(int x, int y):this()
    {
        X = x;
        Y = y;
    }

    public int X { get; set; }
    public int Y { get; set; }

    public ExactLocation ToExactLocation()
    {
        return new ExactLocation {X = this.X, Y = this.Y};
    }

    // Other stuff
}

If you need this, this is the exact location of the struct:

public struct ExactLocation
{
    public double X { get; set; }
    public double Y { get; set; }

    // Various Operator Overloads, but no constructor
}

And here is what I call it:

someScreenLocation = MethodThatGivesAScreenLocation();
if (DestinationLocation == someScreenLocation.ToExactLocation())
{
     // Do stuff
}

When I do this, ReSharper puts it in "Impure Method is called for readonly field of value type."

Why is this so? And what can I do to make it disappear?

+5
source share
6 answers

This is not clean because it does not return a value that depends only on its input. When the value Xor Ychanges in the same way as the return value ToExactLocation, i.e. Its output depends on the internal, variable state.

, X Y ExactLocation . ScreenLocation .

someScreenLocation . ToExactLocation , . reaodnly, , . , , , . .

, .

EDIT:

...

struct Point
{
    int X;
    int Y;
    bool Mutate() { X++; Y++; }
}

class Foo
{
    public readonly Point P;
    Foo() 
    { 
        P = new Point();
        P.Mutate();  // impure function on readonly value type
    }
}

Mutate(), P . P , .

+8

, ( ) ().

.ToExactLocation() , , .

Resharper , ( ). , , ​​ , , .X .Y .

+6

, , pure . f(x) = x^2 + 2x + 10 10, x 0.

, ToExactLocation() , , , , "".

+3

2 " ": ( / ), - , ReSharper .

, . :

var someScreenLocation = new ScreenLocation(1,1);

var locationOne = someScreenLocation.ToExactLocation();
var locationTwo = someScreenLocation.ToExactLocation();
someScreenLocation.X = 3;
var locationThree = someScreenLocation.ToExactLocation();

, ( , , ). , locationOne locationTwo ( ), , , locationThree , ( ) .

, X Y readonly ( ).

ReSharper , - , Pure, .

, ReSharper "" readonly. ReSharper:

struct Point
{
    public int X;
    public int Y;
    public Point(int x, int y){X = x;Y = y;}

    public void Mutate(){X++;}
    public Point TheoreticallyPure(){return new Point(1, 1);}
    [Pure] public Point MarkedPure(){ return new Point(1, 1);}
}

class WithReadonlyField
{
    public readonly Point P;
    public WithReadonlyField()
    {
        P = new Point();
        P.TheoreticallyPure();  // impure function on readonly value type
        P.MarkedPure(); // return value of pure not used
        P.Mutate();   // impure function on readonly value type - modifies P.
        P = new Point().MarkedPure(); // ok to modify P multiple times.
    }
    public void NormalMethod()
    {
        P.Mutate();   // impure function on readonly value type, no changes to P
    }
}

# readonly , ReSharper "" ( , Mutate readonly P, NormalMethod, ).

" readonly... , , "

, ReSharper , .

+2

It would be better to simulate this as a static method (for any class) and get rid of an unclean warning. The explanation is omitted, as other answers relate to why already.

Example:

public static ExactLocation ToExactLocation(ScreenLocation loc)
{
    return new ExactLocation {X = loc.X, Y = loc.Y};
}

or use the extension method

public static ExactLocation ToExactLocation(this ScreenLocation loc)
{
    return new ExactLocation {X = loc.X, Y = loc.Y};
}
+1
source

Not sure about the reason, and I would put this as a comment if it was formatted correctly ...

Would you like something like:

var someScreenLocation = MethodThatGivesAScreenLocation();
if (DestinationLocation.X == someScreenLocation.ToExactLocation().X &&
    DestinationLocation.Y == someScreenLocation.ToExactLocation().Y)
{
     // Do stuff
}
0
source

All Articles