Skip to content

Improving PdfPoint#54

Merged
EliotJones merged 3 commits intoUglyToad:masterfrom
BobLd:master
Aug 10, 2019
Merged

Improving PdfPoint#54
EliotJones merged 3 commits intoUglyToad:masterfrom
BobLd:master

Conversation

@BobLd
Copy link
Collaborator

@BobLd BobLd commented Aug 9, 2019

Adding:

  • ToDouble
  • Equals
  • GetHashCode

Not sure if GetHashCode is properly done, any feedback welcome.

Copy link
Member

@EliotJones EliotJones left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for adding these to PdfPoint, they're definitely needed and should help consumers out. I'd recommend changing the ToDouble return type but I'm aware this might have knock-on impacts for any code you were working on that needed an array. Let me know if it's unworkable for you and maybe we can have the array based implementation as an extension method,

/// <returns></returns>
public override bool Equals(object obj)
{
if (obj is PdfPoint)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a slightly terser syntax for this:

Suggested change
if (obj is PdfPoint)
if (obj is PdfPoint point)

Then you can remove line 103, but I don't mind, I just know Resharper is going to nag me 😆

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very good, thx!

/// Converts this <see cref="PdfPoint"/> into an array.
/// </summary>
/// <returns></returns>
public double[] ToDouble()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if this would be better as a ValueTuple rather than an array. Since the array will always be known to have 2 members a tuple has a couple of benefits:

  • Prevents incorrect indexing by consumers
  • Avoids an allocation on the heap which needs garbage collection

This would look something like:

Suggested change
public double[] ToDouble()
/// <summary>Converts this <see cref="PdfPoint" to double values.<.summary>
public (double x, double y) ToDouble()

I think PdfPig already includes ValueTuple as a dependency (it's a nuget package for earlier versions of the .NET Framework) so all consumers will be able to use it.

(secondary nitpick on the empty <returns> tags).

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On this, I would really need a double array for computation purpose...

Copy link
Member

@EliotJones EliotJones Aug 10, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I'd be tempted to leave this off the public API for now. My gut instinct is that it'll confuse consumers of the library over the alternative of having a tuple. You could add:

public static class PdfPointExtensions
{
    public static double[] AsDoubleArray(this PdfPoint point) => new [] { (double)point.X, (double)point.Y };
}

Either to your consumer code or to PdfPig (or internally to PdfPig if it's for layout analysis code internally) but I'd avoid having it as a method directly on the public API of PdfPoint for now to reduce the amount of autocomplete options.

Copy link
Collaborator Author

@BobLd BobLd Aug 10, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

okay, you are right. Let's keep it simple and leave it out for the moment

/// <returns></returns>
public override int GetHashCode()
{
return (int)(this.X * 10_000 + 31 * this.Y * 10_000);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overriding GetHashCode is one of those annoying things that we're told to do but correct approaches to it aren't really documented anywhere. There's a couple of discussions on it:

Initially I thought the approach here might be more vulnerable to collisions but now I'm not so sure, though I guess the only way to be sure is calculate the collision rate or something. I tend to treat hash codes as something like encryption in that they're much easier to use library functions for and easy to get wrong when written from scratch.

I generally rely on Resharper when doing this which generates something that closely matches Jon Skeet's answer. For reference this looks something like:

public override int GetHashCode()
{
    var hashCode = 1861411795;
    hashCode = hashCode * -1521134295 + X.GetHashCode();
    hashCode = hashCode * -1521134295 + Y.GetHashCode();
    return hashCode;
}

The other option is to let the .NET Framework do the heavy lifting by relying on the ValueTuple implementation:

return (X, Y).GetHashCode();

Which turns the point into a ValueTuple and uses the implementation from that which is here: https://github.com/dotnet/roslyn/blob/master/src/Compilers/Test/Resources/Core/NetFX/ValueTuple/ValueTuple.cs#L297. Now I'm not sure what that does but I'd hope it's one of the best possible implementations.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hehe exactly. Let's .Net do the job then!

@EliotJones EliotJones merged commit 2d6e494 into UglyToad:master Aug 10, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants