Skip to content

Commit

Permalink
Simplifying the readme for nuget package
Browse files Browse the repository at this point in the history
  • Loading branch information
lookbusy1344 committed Nov 20, 2023
1 parent 1faaee1 commit 8bf612a
Show file tree
Hide file tree
Showing 2 changed files with 2 additions and 98 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ It was built for C# 12 and .NET 8. It checks `record class` and `record struct`
- Otherwise all members are checked for:
- the member is a primitive type, enum or string (these are ok)
- it is a object or dynamic (these are never ok)
- it is an inline array (these are never ok) - new in version 1.2 for .NET 8
- it is an inline array (these are never ok) - **new in version 1.2 for .NET 8**
- it has Equals(T) or Equals(object) method overriden directly in the type (these are ok)
- it is a record (these will be checked elsewhere, so are assumed ok here)
- it is a class (without Equals method, these are not ok)
Expand Down
98 changes: 1 addition & 97 deletions RecordValueAnalyser.Package/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ It was built for C# 12 and .NET 8. It checks `record class` and `record struct`
- Otherwise all members are checked for:
- the member is a primitive type, enum or string (these are ok)
- it is a object or dynamic (these are never ok)
- it is an inline array (these are never ok) - new in version 1.2 for .NET 8
- it is an inline array (these are never ok) - **new in version 1.2 for .NET 8**
- it has Equals(T) or Equals(object) method overriden directly in the type (these are ok)
- it is a record (these will be checked elsewhere, so are assumed ok here)
- it is a class (without Equals method, these are not ok)
Expand Down Expand Up @@ -110,99 +110,3 @@ public record struct Test(IReadOnlyList<int> Numbers)
```

It is not necessary for records to implement `IEquatable<T>`. When you write your implementations `SequenceEqual` is very useful for comparing collections.

Note that GetHashCode for collections is tricky!

```
public override int GetHashCode() => Numbers.GetHashCode(); // BROKEN!
public override int GetHashCode() => HashCode.Combine(Numbers); // BROKEN!
public override int GetHashCode() // CORRECT IMPLEMENTATION
{
var hash = new HashCode();
foreach (var n in Numbers) hash.Add(n);
return hash.ToHashCode();
}
public readonly bool Equals(Test other) => Numbers.SequenceEqual(other.Numbers); // CORRECT IMPLEMENTATION
```

## Examples

These are taken from the test project. Members expected to pass are named `Pass`, and those expected to fail are named `Fail`.

```
// these check members, called parameters in Roslyn
public record class A(F FooFail, G BarFail, string SPass, StructA SaFail);
public record class B(int IPass, IReadOnlyList<int> JFail, int? NullableIntPass, StructB BaPass);
public record struct AS(F FooFail, G GShouldFail, H HShouldPass, string SPass, Inner InnPass, object OFail);
public record struct Tup1(int IPass, (int a, int b) TupPass, DateTime? DtPass);
public record struct Tup2(int IPass, (int a, int[] b, object o) TupFail);
public record struct Tup3(int IPass, (bool, int) TupPass);
// this checks fields and properties
public record class RecFields(int IPass, string SPass, object OFail)
{
public IList<string>? FieldFail;
public int[]? PropertyFail { get; set; }
public int FieldPass;
public string? PropertyPass { get; set; }
//uncomment, and the failures will disappear
//public virtual bool Equals(RecFields? other) => true;
public override int GetHashCode() => 0; // TODO
}
// the record class has an Equals method, so its assumed to be ok
public record class HasEqualsRecordClass(IReadOnlyList<int> NumsPass)
{
public virtual bool Equals(HasEqualsRecordClass? other) => other != null && NumsPass.SequenceEqual(other.NumsPass);
public override int GetHashCode() => 0; // TODO
}
// the record struct has an Equals method, so its assumed to be ok
public record struct HasEqualsRecordStruct(IReadOnlyList<int> NumsPass)
{
public readonly bool Equals(HasEqualsRecordStruct other) => NumsPass.SequenceEqual(other.NumsPass);
public override readonly int GetHashCode() => 0; // TODO
}
// ============= Supporting types =============
// this is nested inside another record
public record Inner(int IPass, string JPass, DateTime DtPass);
// when used in record, this fails because it is a class with no Equals method
public class F { public int[]? n; }
// when used in record, this fails because it is a class with no Equals method
public class G { public int i; }
// when used in record, this passes because it has Equals(T)
public class H
{
public int i;
public bool Equals(H? other) => other != null && other.i == this.i;
//public override bool Equals(object? obj) => Equals(obj as H);
public override int GetHashCode() => 0; // TODO
}
// when used in a record, this fails because no Equals method
public struct StructA { public int[] Numbers; }
// when used in a record, this passes because its fields have value semantics
public struct StructB { public int A; public string S; }
```

0 comments on commit 8bf612a

Please sign in to comment.