I'm seeing some odd behaviour after using FirstOrDefault() on a collection of structs. I've isolated it into this reproduction case. This program won't compile
using System; using System.Linq;  namespace MyProgram {     public class Program {         static void Main() {              var users = new User[] {             new User() { UserGuid = Guid.NewGuid(), Username = "user01" },             new User() { UserGuid = Guid.NewGuid(), Username = "user02" }         };              var user = users.FirstOrDefault(u => u.Username == "user01");             Console.WriteLine(user == default(User) ? "not found" : "found");         }      }      public struct User {         public Guid UserGuid;         public string Username;     } }   The compiler error is the rather cryptic:
Operator '==' cannot be applied to operands of type 'MyProgram.User' and 'MyProgram.User'
Changing the struct to a class works fine - but I'm at a loss as to why I can't compare a struct 'instance' to a default?
* Structs have statically-dispatched methods and properties; there's no ability to override.
C# does not allow a struct to declare a default, no-parameters, constructor. The reason for this constraint is to do with the fact that, unlike in C++, a C# struct is associated with value-type semantic and a value-type is not required to have a constructor.
Yes if the structure is of the same type.
For classes, the == operator uses reference equality. Of course, structs are value types, so they can't be compared by reference. There is no default implementation of == for structs because memberwise comparison isn't always a valid comparison, depending on the type.
You can instead use the Object.Equals method, which does compare memberwise:
Console.WriteLine(user.Equals(default(User)) ? "not found" : "found");   Or you could just implement == to call Object.Equals:
public static bool operator ==(User lhs, User rhs) {     return lhs.Equals(rhs); }   However, the default implementation of Equals for structs uses reflection, and so is very slow. It would be better to implement Equals yourself, along with == and != (and possibly GetHashCode too):
public override bool Equals(Object obj) {     return obj is User && Equals((User)obj); }  public bool Equals(User other) {     return UserGuid == other.UserGuid && Username == other.Username; }  public static bool operator ==(User lhs, User rhs) {     return lhs.Equals(rhs); }  public static bool operator !=(User lhs, User rhs) {     return !lhs.Equals(rhs); } 
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With