• 运算符重载 hash原理 Equals方法


    • 重载的方法提供转换的实现

    ->定义隐式转换使用关键字 implicit

    ->定义显式转换使用关键字 explicit

    ->转换顺序与定义顺序相同

      ->变量1=变量2  对应参数 类型1(类型2 value)

    ->语法:

    [访问修饰符] static[implicit[explicit]] Operator 目标类型(待转换类型 value)

    {

      目标类型 0=new 目标类型();

      //赋值操作,显示操作可以将赋值操作用checked{}块包起来,如放不下,就异常

      return 0;

    }

     class Program
        {
            static void Main(string[] args)
            {
                Person p = new Person();
                Person p1 = new Person();
                p1.Age = 25;
                p.Age = 34;
                int num1 = p;
                int num2 = p + p1;
    
            }
        }
        class Person
        {
            public int Age
            {
                set;
                get;
            }
            public static implicit operator int(Person p){
                return p.Age;
            }
            public static int operator +(Person p1, Person p2)
            {
                return p1.Age + p2.Age;
            }
        }

    • string字符串

    string的常用方法前面博客已有记载,此处补充说明,string类的比较方法

    -》==单个字符进行比较

    -》Equal() 可以进行控制的比较。

       bool <object>.Equals(object o);

       bool<string>.Equals(string str);

       bool string.Equals(string str1,string str2)

       int string.Compare(string str1,string str2);

    用反编译工具查看String。Equals()

    其中object.ReferenceEquals(this,obj)表示比较地址

    return EqualsHelper(this,strB);里面是逐个字符比较

     string str1 = new string(new char[] { 'a', 'b', 'c' };
     string str2 = "abc";
     string str3 = "abc";
     Console.WriteLine(str1.Equals(str2));//结果为true
     Console.WriteLine(str2.Equals(str3));//结果为True
     Console.ReadKey();

    str2与str3内存地址相同(string字符串拘留池),故两个str1与str2相等。str1与str2内存地址不同,但结果还是为true,二者相等,这事因为string.Equals()方法已经重写object的Equal()方法。重写的Equals()方法内部有个EqualsHelper(this,strB)方法,该方法在判断二者的地址不相同,且二者都部位null对象的时候执行。遍历字符串的每个字符,逐个比较。


    hashtable实现的原理简介:

      class Program
        {
            static void Main(string[] args)
            {
                ZQHash h = new ZQHash();
                h.Add("张三", 19);
                h.Add("王五", 29);
            }
        }
        class ZQHash
        {
            object[] keys = new object[255];
            object[] values = new object[255];
            public void Add(object k, object value)
            {
                //调用object的GetHashCode得到一个数字作为索引
                int index = Math.Abs(k.GetHashCode() % 256);//此处需要考虑若生成重复的数字索引的情况
                keys[index] = k;
                values[index] = value;
            }
            public object this[object key]
            {
                get {
                    int index = Math.Abs(key.GetHashCode() % 256);
                    return values[index];
                }
            }
        }

     Contains()方法

     ArrayList list = new ArrayList();
     int[] nums = { 1, 2, 3, 1, 4 };
     list.AddRange(nums);
     if (list.Contains(3))
     {
         Console.WriteLine("包含数字3");
     } 
             ArrayList list2 = new ArrayList();
             string str = "abc";
             string str1 = new string(new char[] { 'a', 'b', 'c' });
             string str2 ="abc";
             list2.Add(str);
             Console.WriteLine(list2.Contains(str1));//结果为true
             // 因为contains里的Equals()方法是重写了object的Equals(),逐个比较字符串里的每个字符
          Console.WriteLine(str2.Contains(str2));//结果为true
       ArrayList list1 = new ArrayList();
       Person p1 = new Person("王五", '', 26);
       Person p2=new Person("李四",'',29);
       Person p3 = new Person("王五",'',26);
       list1.Add(p1);
       list1.Add(p2);
       if (list1.Contains(p3))//结果为不存在王五
      {
           Console.WriteLine("存在王五");
       }
       else
       {
            Console.WriteLine("不存在王五");
       } 
        Console.ReadKey();

    用反编译工具查看Contains()方法内部:

     内部的Equal()方法是继承自object的。object的Equals()方法比较的是地址。因为p3和p1虽然内部数据相等,但二者的指向的地址不一样,所以结果为不存在王五。

    若想要程序认为p1和p3相等,我们需要重写object的Equals()方法。

    在Person类里定义Equals()重写方法

        public override bool Equals(object obj)
            {
                Person p = obj as Person;
                if (p==null)
                {
                    return false;
                }
                if (object.ReferenceEquals(this,p))//比地址不要用等号,因为==可能会有运算符重载的情况
                {
                    return true;
                }
                return this.Age == p.Age && this.Gender == p.Gender && this.Name == p.Name;
            }
    •  Hashtable的遍历
    namespace Foreach遍历的原理
    {
        /// <summary>
        /// 定义一个集合类,并实现IEnumerable接口,以使得它可以用foreach遍历
        /// </summary>
        class ZQCollection:IEnumerable
        {
            ArrayList list;//定义一个线性集合的字段
            public ZQCollection()//构造函数,用来初始化线性集合的字段
            {
                list = new ArrayList();
            }
            public object this[int index]//定义一个索引器,以使得该集合类可以当作数组来使用
            {
                get
                {
                    return list[index];
                }
                set
                {
                    list[index] = value;
                }
            }
            public int Count//定义一个Count属性,以使得该类像集合一样拥有Count属性
            {
                get { return list.Count; }
            }
            public void Add(object obj)//定义一个Add()方法,以使得该类像集合一样有Add()
            {
                list.Add(obj);
            }
            public IEnumerator GetEnumerator()//定义一个获得实现了IEnumerator接口的枚举器的方法
            {
                return new ZQIEnumerator(list);
            }
            protected class ZQIEnumerator : IEnumerator  //封装一个类,用老作为枚举器,实现接口IEnumerator的所有成员
            {
                int currentIndex = -1;
                ArrayList list;
                public ZQIEnumerator(ArrayList obj)
                {
                 this.list = obj;
                }
                public object Current
                {
                    get { return list[currentIndex]; }
                }
                public bool MoveNext()
                {
                    currentIndex++;
                    return currentIndex < list.Count;
                }
                public void Reset()
                {
                    throw new NotImplementedException();
                }
            }
        }
    }
    View Code
    namespace Foreach遍历的原理
    {
        class Program
        {
            static void Main(string[] args)
            {
                ZQCollection cl = new ZQCollection();
                
                cl.Add("123");//像使用集合一样,给自定义的集合类增加元素
                cl.Add("err");
                cl.Add(120);
                for (int i = 0; i < cl.Count;i++ )//遍历定义集合类
                {
                    Console.WriteLine(cl[i]);
                }
              foreach(var temp in cl)//因为该集合类实现了实现了IEnumerable接口,
              { // 里面有一个获得枚举器的方法,有了枚举器,我们就可以用foreach遍历了
                  Console.WriteLine(temp);
              }
                Console.ReadKey();
            }
        }
    }
    View Code

     以上是按从list的正常排序遍历的。我们也可以把枚举器内部设为反序遍历,只需把枚举器内部修改一下,代码如下

       protected class ZQIEnumerator : IEnumerator  //封装一个类,用老作为枚举器,实现接口IEnumerator的所有成员
            {
                //int currentIndex = -1;
                int currentIndex;
                ArrayList list;
                public ZQIEnumerator(ArrayList obj)
                {
                 this.list = obj;
                 currentIndex = list.Count;
                }
                public object Current
                {
                    get { return list[currentIndex]; }
                }
                public bool MoveNext()
                {
                    currentIndex--;
                    return currentIndex >=0;
                }
                public void Reset()
                {
                    throw new NotImplementedException();
                }
            }
    View Code

    既然我们知道使用foreach遍历集合的原理了,那么我们就很容易理解以下方式也可以实现遍历

     Hashtable hs = new Hashtable();
     for(int i = 0; i < 10;i++ )
     {
        hs.Add(i, i * 11);
     }
     var item=hs.GetEnumerator();
     while(item.MoveNext())
     {
        DictionaryEntry de = (DictionaryEntry)item.Current;
        Console.WriteLine(de.Key + "-" + de.Value);
     }

    或者用for循环遍历

           Hashtable hs = new Hashtable();
           for (int i = 0; i < 10;i++ )
           {
              hs.Add(i, i * 11);
           }
           var item=hs.GetEnumerator();
           for (; item.MoveNext(); )
           {
               DictionaryEntry de1 = (DictionaryEntry)item.Current;
               Console.WriteLine(de1.Key + "---" + de1.Value);
           }

     泛型集合Dictionary与List http://www.cnblogs.com/tobecabbage/p/3484918.html

    其他泛型集合:因其他一般泛型集合都可以用Dictionary或List代替,所以便不一一做介绍

    其中,Hashset<T>  hash集,表示所有数字不重复的集合 

    int[] nums = { 1, 2, 3, 4, 2, 1, 3, 6, 8 };
    HashSet<int> hs = new HashSet<int>(nums);//结果为1,2,3,4,6,8
    nums= hs.ToArray();
  • 相关阅读:
    关于推荐的一个算法工程师访谈,有一些内容值得看看
    Element.Event
    复数输出
    Passenger/Nginx/Debian快速部署Rails
    POJ3678【错误总会让自己有收获的】
    android在其他线程中访问UI线程的方法
    C++运算符重载的方法
    Struts2图片文件上传,判断图片格式和图片大小
    list view Item 里面有ImageButton
    用python实现远程复制 (scp + expect )
  • 原文地址:https://www.cnblogs.com/tobecabbage/p/3535595.html
Copyright © 2020-2023  润新知