9. 演算子のオーバーロードに慣れる
独自の型を構築するときは、演算子のオーバーロードを使用できるかどうかを常に考慮する必要があります
ソートが必要な場合は、2 つのコンパレータ実装があります
class FirstType : IComparable<FirstType> { public string name; public int age; public FirstType(int age) { name = "aa"; this.age = age; } public int CompareTo(FirstType other) { return other.age.CompareTo(age); } } static void Main(string[] args) { FirstType f1 = new FirstType(3); FirstType f2 = new FirstType(5); FirstType f3 = new FirstType(2); FirstType f4 = new FirstType(1); List<FirstType> list = new List<FirstType> { f1,f2,f3,f4 }; list.Sort(); foreach (var item in list) { Console.WriteLine(item); } }
class Program : IComparer<FirstType> { static void Main(string[] args) { FirstType f1 = new FirstType(3); FirstType f2 = new FirstType(5); FirstType f3 = new FirstType(2); FirstType f4 = new FirstType(1); List<FirstType> list = new List<FirstType> { f1,f2,f3,f4 }; list.Sort(new Program()); foreach (var item in list) { Console.WriteLine(item); } } int IComparer<FirstType>.Compare(FirstType x, FirstType y) { return x.age.CompareTo(y.age); } }
Framework ) Class Library) 文字列比較は参照自体ではなく、値比較としてオーバーロードされます
設計の観点から見ると、多くの参照型は文字列型と似ています。同じ ID 番号を持っているので、それは人であると考えます。このとき、Equals メソッドをオーバーロードする必要があります。 一般に、参照型の場合、等しい値の特性を定義する必要があります。 Equals メソッドのみをオーバーライドし、 let == は参照の等価性を示すため、必要な方を比較できます。 演算子「==」と「Equals」は両方とも「値の等価性」と「参照」としてオーバーロードできるため、等価性」を明確にするために、FCL は 2 つのインスタンスが同じ参照であるかどうかを比較するための object.ReferenceEquals(); を提供します。辞書のContainsKeyを判定する場合 キー型のHashCodeなので、その型の特定の値を判定条件にしたい場合はGetHashCodeを再度取得する必要があります もちろんHashCodeを使って判定する方法は他にもあります書き換えないと他の問題が発生する可能性があります。影響public override int GetHashCode() { //这样写是为了减少HashCode重复的概率,至于为什么这样写我也不清楚。。 记着就行 return (System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName + "#" + age).GetHashCode(); }
class FirstType : IEquatable<FirstType> { public string name; public int age; public FirstType(int age) { name = "aa"; this.age = age; } public override bool Equals(object obj) { return age.Equals(((FirstType)obj).age); } public bool Equals(FirstType other) { return age.Equals(other.age); } public override int GetHashCode() { return (System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName + "#" + age).GetHashCode(); } }
class Person : IFormattable { public override string ToString() { return "Default Hello"; } public string ToString(string format, IFormatProvider formatProvider) { switch (format) { case "Chinese": return "你好"; case "English": return "Hello"; } return "helo"; } }
static void Main(string[] args) { Person p1 = new Person(); Console.WriteLine(p1); Console.WriteLine(p1.ToString("Chinese",null)); Console.WriteLine(p1.ToString("English", null)); }
IFormatProvider インターフェイスもありますが、まだ勉強していません
14. 浅いコピーと深いコピーを正しく実装する
出力はオリジナルです ディープ コピーは参照型用です。理論的には、文字列型は参照型です。ただし、参照型の特殊な性質により、 Object.MemberwiseClone はまだそのコピーを作成します。つまり、浅いコピー プロセス中に、文字列をコピーする必要があります。文字列を値型として扱います
15。ダイナミックを使用してリフレクションの実装を簡素化します
//记得在类前添加[Serializable]的标志 [Serializable] class Person : ICloneable { public string name; public Child child; public object Clone() { //浅拷贝 return this.MemberwiseClone(); } /// <summary> /// 深拷贝 /// 我也不清楚为什么这样写 /// </summary> /// <returns></returns> public Person DeepClone() { using (Stream objectStream = new MemoryStream()) { IFormatter formatter = new BinaryFormatter(); formatter.Serialize(objectStream, this); objectStream.Seek(0, SeekOrigin.Begin); return formatter.Deserialize(objectStream) as Person; } } } [Serializable] class Child { public string name; public Child(string name) { this.name = name; } public override string ToString() { return name; } }
ダイナミックを使用すると、リフレクションを使用して記述されたコードよりも美しく簡潔になることがわかります。また、ダイナミックは初回実行後にキャッシュされるため、複数回の実行の効率も高くなります。
その差は 10 倍近くあります。
これは 100 回実行した結果です
しかし、多くの場合、効率は必要ありません。リフレクションの実装を簡素化するために常に動的を使用することをお勧めします。
##関連記事:C# 学習記録: ライティング高品質なコードの改善と提案の整理 1-3
C# 学習記録: 高品質なコードの作成と改善案の整理 4-8
以上がC# 学習記録: 高品質のコードの作成と組織の改善に関する提案 9-15の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。