diff --git a/src/Main/Base/Project/Src/TextEditor/Commands/CodeGenerators/EqualsCodeGenerator.cs b/src/Main/Base/Project/Src/TextEditor/Commands/CodeGenerators/EqualsCodeGenerator.cs index 727918e94c..7dd627d3a7 100644 --- a/src/Main/Base/Project/Src/TextEditor/Commands/CodeGenerators/EqualsCodeGenerator.cs +++ b/src/Main/Base/Project/Src/TextEditor/Commands/CodeGenerators/EqualsCodeGenerator.cs @@ -26,14 +26,30 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Commands { TypeReference intReference = new TypeReference("System.Int32"); MethodDeclaration method = new MethodDeclaration("GetHashCode", Modifiers.Public | Modifiers.Override, intReference, null, null); - Expression expr = CallGetHashCode(new IdentifierExpression(currentClass.Fields[0].Name)); - for (int i = 1; i < currentClass.Fields.Count; i++) { - IdentifierExpression identifier = new IdentifierExpression(currentClass.Fields[i].Name); - expr = new BinaryOperatorExpression(expr, BinaryOperatorType.ExclusiveOr, - CallGetHashCode(identifier)); - } method.Body = new BlockStatement(); - method.Body.AddChild(new ReturnStatement(expr)); + + VariableDeclaration var; + var = new VariableDeclaration("hashCode", new PrimitiveExpression(0, "0"), intReference); + method.Body.AddChild(new LocalVariableDeclaration(var)); + + Expression expr; + + foreach (IField field in currentClass.Fields) { + expr = new AssignmentExpression(new IdentifierExpression(var.Name), + AssignmentOperatorType.ExclusiveOr, + new InvocationExpression(new FieldReferenceExpression(new IdentifierExpression(field.Name), "GetHashCode"))); + if (IsValueType(field.ReturnType)) { + method.Body.AddChild(new ExpressionStatement(expr)); + } else { + method.Body.AddChild(new IfElseStatement( + new BinaryOperatorExpression(new IdentifierExpression(field.Name), + BinaryOperatorType.ReferenceInequality, + new PrimitiveExpression(null, "null")), + new ExpressionStatement(expr) + )); + } + } + method.Body.AddChild(new ReturnStatement(new IdentifierExpression(var.Name))); nodes.Add(method); TypeReference boolReference = new TypeReference("System.Boolean"); @@ -49,14 +65,14 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Commands expr = new UnaryOperatorExpression(expr, UnaryOperatorType.Not); method.Body.AddChild(new IfElseStatement(expr, new ReturnStatement(new PrimitiveExpression(false, "false")))); - expr = new BinaryOperatorExpression(new ThisReferenceExpression(), - BinaryOperatorType.Equality, - new IdentifierExpression("obj")); - method.Body.AddChild(new IfElseStatement(expr, new ReturnStatement(new PrimitiveExpression(true, "true")))); +// expr = new BinaryOperatorExpression(new ThisReferenceExpression(), +// BinaryOperatorType.ReferenceEquality, +// new IdentifierExpression("obj")); +// method.Body.AddChild(new IfElseStatement(expr, new ReturnStatement(new PrimitiveExpression(true, "true")))); - VariableDeclaration var = new VariableDeclaration("my" + currentClass.Name, - new CastExpression(currentType, new IdentifierExpression("obj"), CastType.Cast), - currentType); + var = new VariableDeclaration("my" + currentClass.Name, + new CastExpression(currentType, new IdentifierExpression("obj"), CastType.Cast), + currentType); method.Body.AddChild(new LocalVariableDeclaration(var)); expr = TestEquality(var.Name, currentClass.Fields[0]); @@ -70,16 +86,39 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Commands nodes.Add(method); } - static InvocationExpression CallGetHashCode(Expression expr) + static bool IsValueType(IReturnType type) + { + IClass c = type.GetUnderlyingClass(); + return c != null && (c.ClassType == Dom.ClassType.Struct || c.ClassType == Dom.ClassType.Enum); + } + + static bool CanCompareEqualityWithOperator(IReturnType type) { - return new InvocationExpression(new FieldReferenceExpression(expr, "GetHashCode")); + // return true for value types except float and double + // return false for reference types except string. + IClass c = type.GetUnderlyingClass(); + return c != null + && c.FullyQualifiedName != "System.Single" + && c.FullyQualifiedName != "System.Double" + && (c.ClassType == Dom.ClassType.Struct + || c.ClassType == Dom.ClassType.Enum + || c.FullyQualifiedName == "System.String"); } static Expression TestEquality(string other, IField field) { - return new BinaryOperatorExpression(new FieldReferenceExpression(new ThisReferenceExpression(), field.Name), - BinaryOperatorType.Equality, - new FieldReferenceExpression(new IdentifierExpression(other), field.Name)); + if (CanCompareEqualityWithOperator(field.ReturnType)) { + return new BinaryOperatorExpression(new FieldReferenceExpression(new ThisReferenceExpression(), field.Name), + BinaryOperatorType.Equality, + new FieldReferenceExpression(new IdentifierExpression(other), field.Name)); + } else { + InvocationExpression ie = new InvocationExpression( + new FieldReferenceExpression(new TypeReferenceExpression("System.Object"), "Equals") + ); + ie.Arguments.Add(new FieldReferenceExpression(new ThisReferenceExpression(), field.Name)); + ie.Arguments.Add(new FieldReferenceExpression(new IdentifierExpression(other), field.Name)); + return ie; + } } public override bool IsActive { diff --git a/src/Setup/Files.wxs b/src/Setup/Files.wxs index cfb1c61658..ebcd2163a5 100644 --- a/src/Setup/Files.wxs +++ b/src/Setup/Files.wxs @@ -73,7 +73,7 @@ - + @@ -94,7 +94,7 @@ - + @@ -1253,4 +1253,4 @@ - \ No newline at end of file +