C#拾遗系列(9):继承、接口、扩展方法、分部类、类操作、Ref and Out、可空类型...

本文内容:

  • 继承
  • Equal示例
  • 结构和类
  • 属性
  • Ref and Out
  • 类操作
  • 扩展方法
  • 接口
  • 可空类型
  • 分部类

 

1. 继承

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

namespace NetTest

{

    public class Animal

    {

        public virtual void Fly()

        {

            Console.Out.WriteLine("Animal Fly");

            Console.Out.WriteLine("----------------------------");

        }

    }

    public class Dog : Animal

    {

        public new virtual void Fly()

        {

            base.Fly();

            Console.Out.WriteLine("Dog  can't Fly");

            Console.Out.WriteLine("----------------------------");

        }

        //也可以,但子类不能再覆盖了

        //public new  void Fly()

        //{

        //    base.Fly();

        //    Console.Out.WriteLine("Dog can't Fly");

        //    Console.Out.WriteLine("----------------------------");

        //}               

    }

    public class Cat : Animal

    {

        public override void Fly()

        {

            base.Fly();

            Console.Out.WriteLine("Cat can't fly");

            Console.Out.WriteLine("----------------------------");

        }

 

        public override string ToString()

        {

            return "I am a happy cat,wow";

        }

 

    }

 

    public class InheritTest

    {

        public void Test()

        {

            /*

           new 和 overide的区别是,当把子类付给父类变量时,new 将调用父类的方法,而override将调用子类的方法       

           */

            Animal dog = new Dog();

            dog.Fly();

            /* 输出

            Animal Fly   

            */

 

            Animal cat = new Cat();

            cat.Fly();

 

            /* 输出

            Animal fly

            Cat can't Fly           

            */

            Console.Out.WriteLine(cat.ToString());

 

        }

    }

}

 

2. Equal 示例

 

 

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

 

namespace NetTest

{

    public class EqualsTest

    {

        public void testEquals()

        {

            /*C# 中有两种不同的相等:引用相等和值相等。

            值相等是大家普遍理解的意义上的相等:

            它意味着两个对象包含相同的值。例如,两个值为 2 的整数具有值相等性。

            引用相等意味着要比较的不是两个对象,而是两个对象引用,且两者引用的是同一个对象                    

            若要检查引用相等性,应使用 ReferenceEquals。若要检查值相等性,请使用 Equals。           

            */

            object a = new object();

            object b = a;

            Console.Out.WriteLine(System.Object.ReferenceEquals(b, a));

 

            int c = 2;

            int d = 3;

            Console.Out.WriteLine(c.Equals(d));           

        }

    }

}

 

 

3.  结构和类

 

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

/*   

    结构具有以下特点:结构是值类型,而类是引用类型。

    与类不同,结构的实例化可以不使用 new 运算符。  

    结构可以声明构造函数,但它们必须带参数。      

    一个结构不能从另一个结构或类继承,而且不能作为一个类的基。所有结构都直接继承自 System.ValueType,后者继承自 System.Object。

    结构可以实现接口。                                                                                              

    结构可用作可为 null 的类型,因而可向其赋 null 值。                                                      

*/ 

namespace NetTest

{

    struct StructAndClass

    {

        /*

        * 结构不能包含无参构造函数

        public StructAndClass(){ }

        */

 

        public StructAndClass(int age, string name)

        {

            this.age = age;

            this.name = "jack";

        }

        public int age;

        public string name;

    }

   public class TestStrcutAndClass

    {

        public void TestSAC()

        {

            StructAndClass a = new StructAndClass();

            a.age = 10;

            a.name = "jack";

            Console.Out.WriteLine(a.age + ":" + a.name);

            StructAndClass b = new StructAndClass(20, "wang");

            Console.Out.WriteLine(b.age + ":" + b.name);

        }

    }

}

 

4. 属性

 

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

 

namespace NetTest

{

    public class TestAttribute

    {

        public void Test()

        {           

            PrintAuthorInfo(typeof(CustomAttribute));       

        }

 

        /*

        Obsolete 属性将某个程序实体标记为一个建议不再使用的实体。每次使用被标记为已过时的实体时,

        随后将生成警告或错误,这取决于属性是如何配置的,第二个参数是true时,编译时显示错误

        */

        [Obsolete("please use aonther method,this is obsolate",true)]

        public void TestObsolate()

        {

            Console.Out.WriteLine("welcome");

 

        }

        private static void PrintAuthorInfo(System.Type t)

        {

            System.Console.WriteLine("Author information for {0}", t);

            System.Attribute[] attrs = System.Attribute.GetCustomAttributes(t);  // reflection

 

            foreach (System.Attribute attr in attrs)

            {

                if (attr is Author)

                {

                    Author a = (Author)attr;

                    System.Console.WriteLine("   {0}, version {1:f}", a.Name, a.version);

                }

            }

        }

        //应用自定义属性

        [Author("Jack",version=1.0)]

        [Author("TJ",version=2.0)]

        class CustomAttribute

        {

            public void Test()

            {

 

                Console.Out.WriteLine("Test custom attribute");

            }       

        }

        //自定义的属性,集成属性类

        [System.AttributeUsage(AttributeTargets.Class|AttributeTargets.Struct,AllowMultiple=true)]

        class Author : System.Attribute

        {

            private string name;

            public double version;

 

            public Author(string name)

            {

                this.name = name;

                version = 1.0;

            }

 

            public string Name

            {

 

                get { return this.name; }

            }

 

        }

    }

 

}

 

5. Ref and Out

 

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

 

namespace NetTest

{

   public  class TestRefOut

    {

       private Shape s;

       private Shape d;

 

       /* 传递到 ref 参数的参数必须最先初始化。这与 out 不同,后者的参数在传递之前不需要显式初始化 ,out 必须在方法内部赋值

       尽管 ref 和 out 在运行时的处理方式不同,但在编译时的处理方式相同。因此,如果一个方法采用 ref 参数,

       而另一个方法采用 out 参数,则无法重载这两个方法

        属性不是变量,因此不能作为 ref 参数传递

        */

       private void Test(ref Shape a, out Shape b)

       {

           //a = "good";

           b = new Shape();

           b.width = 500;

           Console.Out.WriteLine(a.width);

       }

       public void Test()

       {

           s = new Shape();

           s.width = 200;

           Test( ref s, out d);

           Console.Out.WriteLine(d.width);

 

       }

    }

 

   public class Shape

   {

       public int width;

       public int length;

   }

}

 

6. 类操作

 

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

 

namespace NetTest

{

   public class OperationOveride

    {

       public void TestOperationOverid()

       {

           Complex c1 = new Complex(10, 2);

           Complex c2 = new Complex(5, 4);

           Complex c3 = c1 + c2;

           Console.Out.WriteLine(c3.real + "," + c3.imaginary);       

       }      

    }

 

    public struct Complex

    {

        public int real;

        public int imaginary;

 

        public Complex(int real, int image)

        {

            this.real = real;

            this.imaginary = image;

        }

 

        public static Complex operator +(Complex c1, Complex c2)

        { 

            return new Complex(c1.real + c2.real, c1.imaginary + c2.imaginary);

        }

 

    }

}

 
7. 扩展方法
 

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

 

//Description: 扩展方法

namespace NetTest

{

    public class TestExtendMethod

    {

        public void Test()

        {

            Jack my = new Jack();

            my.showSmile();

            int i = 5;

            Console.Out.WriteLine(i.addAge(10));

 

        }

    }

    public class Jack

    {

        public void Smile()

        {

            Console.Out.WriteLine("Jack smile");

        }

    }

 

    /*

    扩展方法使您能够向现有类型“添加”方法,而无需创建新的派生类型、重新编译或以其他方式修改原始类型。

    扩展方法是一种特殊的静态方法,但可以像扩展类型上的实例方法一样进行调用。

    对于用 C# 和 Visual Basic 编写的客户端代码,调用扩展方法与调用在类型中实际定义的方法之间没有明显的差异.     

 

    在代码中,可以使用实例方法语法调用该扩展方法。但是,编译器生成的中间语言 (IL) 会将代码转换为对静态方法的调用。

    因此,并未真正违反封装原则。实际上,扩展方法无法访问它们所扩展的类型中的私有变量。

 

    可以使用扩展方法来扩展类或接口,但不能重写扩展方法。与接口或类方法具有相同名称和签名的扩展方法永远不会被调用。

    编译时,扩展方法的优先级总是比类型本身中定义的实例方法低。换句话说,

    如果某个类型具有一个名为 Process(int i) 的方法,而您有一个具有相同签名的扩展方法,则编译器总是绑定到该实例方法。

    当编译器遇到方法调用时,它首先在该类型的实例方法中寻找匹配的方法。

    如果未找到任何匹配方法,编译器将搜索为该类型定义的任何扩展方法,并且绑定到它找到的第一个扩展方法。

 

    */

    public static class myExtendmethod

    {

        public static void showSmile(this Jack jack)

        {

            Console.Out.WriteLine("This is Extend method");

        }

 

        public static int addAge(this int s, int b)

        {

            return s + b;

        }

 

    }

 

}

 

8. 接口

 

 

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

 

namespace NetTest

{

   public  interface IJack

    {

        void Happy();

 

    }

 

   public interface ICrystal

    {

        void Happy();

    }

 

   public class Happy: IJack,ICrystal

    {

        #region IJack Members

 

        //不能用限定符如private ,public等

        void IJack.Happy()

        {

            Console.Out.WriteLine("haha");

        }

        #endregion

 

        #region ICrystal Members

 

       //显示实现的成员不能从类直接访问

        void ICrystal.Happy()

        {

            Console.Out.WriteLine("smile");

        }

 

        #endregion 

 

    }

 

   public class TestInterface

   {

       public void Test()

       {

           /*

            同名时,必须转换到接口才能调用,两个方法实现都是分离的,都不可以直接在类中使用

            */

 

           /*

           Happy t = new Happy();   //显示实现的成员不能从类直接访问

           t.(..)

            * */

 

           IJack testHappy =(IJack)new Happy();

 

           testHappy.Happy();

 

           ICrystal testcrystalHappy = (ICrystal)new Happy();

           testcrystalHappy.Happy();

       }

   }

}

 

 

9. 可空类型

 

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

 

namespace NetTest

{

    public  class TestNullable

    {

        public void Test()

        {

            IsNullValue(null);

            IsNullValue(20);

            int? c = null;

 

            //?? 运算符定义在将可以为 null 的类型分配给非可以为 null 的类型时返回的默认值

            int d = c ?? -1;

            Console.Out.WriteLine(d);

 

        }

 

        public void IsNullValue(int? num)

        {

           if (num.HasValue)

            {

                System.Console.Out.WriteLine("num has value:" + num);

                System.Console.Out.WriteLine("num  vaue has value:" + num.Value);

            }

            else

            {

                System.Console.Out.WriteLine("num is null" );

            }

           System.Console.Out.WriteLine(num.GetValueOrDefault());

           System.Console.Out.WriteLine(num.GetValueOrDefault(100));

           System.Console.Out.WriteLine("---------------------");

        }

    }

}

 

 

10. 分部类

  a. 描述:

        分部类或结构可以包含分部方法。类的一个部分包含方法的签名。可以在同一部分或另一个部分中定义可选实现。

        如果未提供该实现,则会在编译时移除方法以及对方法的所有调用。

        分部方法使类的某个部分的实施者能够定义方法(类似于事件)。

        类的另一部分的实施者可以决定是否实现该方法。如果未实现该方法

        编译器将移除方法签名以及对该方法的所有调用。因此,分部类中的任何代码都可以随意地使用分部方法,

        即使未提供实现也是如此。如果调用了未实现的方法,将不会导致编译时错误或运行时错误。

 

        在自定义生成的代码时,分部方法特别有用。这些方法允许保留方法名称和签名,

        因此生成的代码可以调用

阅读更多

没有更多推荐了,返回首页