接口乱谈

一、定义接口

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

     }

原文地址:https://www.cnblogs.com/JustYong/p/3879539.html