How do I properly use List-Vector3-.Contains()?
for some reason I seem to be getting different results with these two different code snippets. In both cases I'm searching a list of Vector3's for a particular Vector3 VALUE.
In all the code below tempVertexList is defined as :
List<Vector3> tempVertexList;
This version uses List.Contains() (Which I though might be faster than "by hand")
//this version seem to fail to find matches
if(tempVertexList.Contains(meshVertices[i]))
found=true;
And, this version is "by hand", which seems to find more matches:
//this version seem to find all matches properly
foreach (Vector3 listVector in tempVertexList)
{
if (listVector == meshVertices[i])
{ found = true; break; }
}
Why do these give different results? Does "Contains" use a different comparison operator? How can I fix that?
Answer by RudyTheDev · Mar 21, 2016 at 12:00 AM
That's because .Contains()
ends up using Vector3.Equals()
(via EqualityComparer<T>.Default
since Vector3
doesn't implement IEquatable
), while manual comparison uses ==
. Equals()
literally compares the x
/y
/z
, while ==
compares magnitudes.
Here's (disassembled) Unity code for Vector3
:
public override bool Equals(object other)
{
if (!(other is Vector3))
return false;
Vector3 vector3 = (Vector3) other;
if (this.x.Equals(vector3.x) && this.y.Equals(vector3.y))
return this.z.Equals(vector3.z);
return false;
}
public static bool operator ==(Vector3 lhs, Vector3 rhs)
{
return (double) Vector3.SqrMagnitude(lhs - rhs) < 0.0 / 1.0;
}
You would need to implement your own EqualityComparer
and pass it to the .NET collections during construction if you want to use things that do equality checks.
"You would need to implement your own EqualityComparer and pass it to the .NET collections during construction if you want to use things that do equality checks." I was afraid it was something like that. Studied for a while how to specify a comparer myself, but kept getting stuck on the fact that Vector3 is sealed. I think the fact that I need to pass it to the container's constructor is what I was missing, I'll try my searches again with that i $$anonymous$$d. $$anonymous$$any thanks for the help!
The comparer itself is just:
public class Vector3Comparer : IEqualityComparer<Vector3>
{
public static readonly Vector3Comparer Default = new Vector3Comparer();
public bool Equals(Vector3 a, Vector3 b) { return a == b; }
public int GetHashCode(Vector3 a) { return a.GetHashCode(); }
}
and then just Vector3Comparer.Default
. But yeah, the List<>
s don't use custom ones, so you'd need to edit Vector3
, which you can't. Works only for stuff like Dictionary
.
Your answer
Follow this Question
Related Questions
List.Contains not working as intended 0 Answers
Find child object that Contains string from list 0 Answers
list.contains problem 1 Answer
Unique list of Vector3's 1 Answer
Sort a list of class by a vector variable in the class 2 Answers