zoukankan      html  css  js  c++  java
  • 接口乱谈

    一、定义接口

         接口对一组方法签名进行了统一命名。定义接口类型时,可指定的可见性为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) //无法通过编译,能提供编译时的类型安全检查

         }

  • 相关阅读:
    HttpClient
    spring入门
    morphia进阶
    morphia基本API方法
    mangodb数据库框架morphia注解
    学与思
    解决vscode执行yarn启动项目报错
    使用swiper+动画实现轮播图自动播放
    vue中使用el-tree实现一行显示多条数据
    使用git命令提交部分修改代码
  • 原文地址:https://www.cnblogs.com/JustYong/p/3879539.html
Copyright © 2011-2022 走看看