• 接口乱谈


    一、定义接口

         接口对一组方法签名进行了统一命名。定义接口类型时,可指定的可见性为public 或 internal,但在[CLR via C#]第3版书中的原话是:"定义接口类型时,可指定你希望的任何可见性/可访问性(public,protected,internal等)",个人认为这句话说得不妥。但无论如何,不嵌套在其他类型中的顶级类型的可访问性只能是 internal 或 public。这些类型的默认可访问性是 internal。

    二、继承接口

        C#编译器要求将用于实现一个接口的方法简称接口方法标记为public。CLR要求将接口方法标记为virtual。如果在源代码中没有显式地将接口方法标记为virtual,编译器会将它们标记为virtual和sealed;这会阻止派生类重写接口方法。如果显式地将接口方法标记为virtual,编译器就会将此方法标记为virtual并保持它的非密封状态,这样一来,派生类就可以重写它。

        值类型可以实现零个或多个接口。不过,将值类型的实例转型为接口类型时,值类型的实例必须装箱。这是由于接口变量是一个引用,它必须指向堆上的一个对象,使CLR能检查对象的类型对象指针,从而判断对象的确切类型。然后,在调用已装箱值类型的一个接口方法时,CLR会跟随对象的类型对象指针,找到类型对象的方法表,从而调用正确的方法。

    三、隐式和显式接口方法实现

        public class SimpleType : IDisposable

        {

              //隐式接口方法实现

              public void Dispose(){ Console.WriteLine("public Dispose");}

              //显式接口方法实现(不允许指定可访问性,但是编译器生成方法的元数据时,其可访问性会被自动设为private)

              void IDisposable.Dispose(){Console.WriteLine("IDisposable Dispose")}

        }

        public static void Main()

       {

             SimpleType st = new SimpleType();

             st.Dispose();//输出结果为"public Dispose"

             IDisposable d = st;

             d.Dispose();//输出结果为"IDisposable Dispose"

        }

    四、泛型接口

          泛型接口提供的好处:

          private void Method1()

          {

              Int32 x = 1, y = 2;

              IComparable c = x;

              c.CompareTo(y);//CompareTo期望接收一个Object类型的参数,传递y没有问题,但是值类型会装箱

              c.CompareTo("2")//可以编译通过,但是在运行时会抛出异常,无法提供编译时类型安全性

          }

          private void Method2()

          {

              Int32 x = 1, y = 2;

              IComparable<Int32> c = x;

              c.CompareTo(y);//CompareTo期望接收一个Int21类型的参数,传递y没有问题,而且y不会装箱

              c.CompareTo("2")//编译错误,可以提供编译时的类型检查

          }

          1.泛型接口提供了出色的编译时类型安全性。

          2.处理值类型时,装箱次数会少得多。

          3.类可以实现同一个接口若干次,只要每次使用不同的类型参数

    五、在不存在泛型接口版本的情况下,怎样实现来增强编译时的类型安全性

          public struct SomeValueType1 : IComparable

          {

                private Int32 _x;

                public SomeValueType(Int32 x){  _x = x; }

                public Int32 CompareTo(Object other)

                {

                     return (_x - ((SomeValueType)other)._x);

                }

          }

           public struct SomeValueType2 : IComparable

          {

                private Int32 _x;

                public SomeValueType(Int32 x){  _x = x; }

                public Int32 CompareTo(SomeValueType2 other)

                {

                     return (_x - other._x);

                }

                Int32 IComparable.CompareTo(Object o)

                {

                    return CompareTo((SomeValueTypes)o);

                }

          }

          public static void Main()

         {

              SomeValueType1 v1 = new SomeValueType1(0);

              Object o = new Object();

              v1.CompareTo(v1); //值类型进行装箱操作

              v1.CompareTo(o) //编译通过,但运行时抛出InvalidCastException,没法进行编译时类型安全的检查

             

              SomeValueType2 v2 = new SomeValueType2(0);

              Object o = new Object();

              v2.CompareTo(v2); //由于调用的是SomeValueType2自身声明的方法,所以不用装箱

              v1.CompareTo(o) //无法通过编译,能提供编译时的类型安全检查

         }

  • 相关阅读:
    Mysql之存储过程与存储函数
    mysql-bin日志自动清理及手动删除
    mysql下面的binlog
    mysql下的数据备份与恢复
    查询mysql数据库中各个表所占空间大小以及索引大小
    mysql执行sql语句报错this is incompatible with sql_mode=only_full_group_by
    docker WARNING: IPv4 forwarding is disabled. 解决方法
    Linux平台修改环境变量的方式
    PuTsangTo
    (一) 从Angular1到Angular2的杂谈
  • 原文地址:https://www.cnblogs.com/JustYong/p/3879539.html
Copyright © 2020-2023  润新知