9. Habituez-vous à la surcharge des opérateurs
Lorsque vous créez vos propres types, vous devez toujours vous demander si vous pouvez utiliser la surcharge des opérateurs
Si vous devez trier, il existe deux implémentations de comparateur
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); } }
ou le deuxième
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); } }
Il appelle la méthode Compare du programme
Que ce soit == ou Equals. :
Pour les types valeur, si les valeurs des types sont égales, il renvoie True
Pour les types référence, si les types pointent vers le même objet, il renvoie True
et ils peuvent tous être surchargés
Pour une classe de référence spéciale comme une chaîne, Microsoft peut penser que sa signification pratique est plus encline à un type valeur, donc en FCL (Fcadre Class L ibrary) la comparaison de chaînes est surchargée en tant que comparaison de valeurs, pas pour la référence elle-même
En termes de conception, de nombreux types de référence seront similaires aux types de chaînes , comme des personnes, d'autres Si leurs numéros d'identification sont les mêmes, nous les considérons comme la même personne. À ce stade, nous devons surcharger la méthode Equals
De manière générale, pour les types de référence, nous avons besoin. pour définir la caractéristique des valeurs égales, et nous devons uniquement remplacer la méthode Equals. et laisser == représenter l'égalité de référence, afin que nous puissions comparer celle que nous voulons
Puisque les deux opérateurs "==" et "Equals" peut être surchargé en tant que « égalité de valeur » et « égalité de référence » », donc par souci de clarté, FCL fournit object.ReferenceEquals(); pour comparer si deux instances sont la même référence
dans le dictionnaire Lors du jugement de ContainsKey, le HashCode du type de clé est utilisé, donc si nous voulons utiliser une certaine valeur dans le type comme condition de jugement, nous devons à nouveau getHashCode . Bien sûr, il existe d'autres méthodes qui utilisent HashCode pour juger si elles sont égales. Si nous ne répétons pas, l'écriture peut produire d'autres effets
public override int GetHashCode() { //这样写是为了减少HashCode重复的概率,至于为什么这样写我也不清楚。。 记着就行 return (System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName + "#" + age).GetHashCode(); }
Lors de la réécriture de la méthode Equals, une interface de type sécurisé IEquatable< T> doit également être fourni à l'avance, donc la version finale de la réécriture de Equals doit être
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)); }
<. 🎜>
//记得在类前添加[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; } }
static void Main(string[] args) { //使用反射 Stopwatch watch = Stopwatch.StartNew(); Person p1 = new Person(); var add = typeof(Person).GetMethod("Add"); for (int i = 0; i < 1000000; i++) { add.Invoke(p1, new object[] { 1, 2 }); } Console.WriteLine(watch.ElapsedTicks); //使用dynamic watch.Reset(); watch.Start(); dynamic d1 = new Person(); for (int i = 0; i < 1000000; i++) { d1.Add(1, 2); } Console.WriteLine(watch.ElapsedTicks); }
La différence est presque 10 fois
C'est le résultat de 100 exécutions
Record d'apprentissage C# : rédaction de suggestions d'amélioration de code de haute qualité 1-3
Record d'apprentissage C# : rédaction de suggestions d'amélioration de code de haute qualité 4-8
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!