`
wangdeshui
  • 浏览: 256921 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

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. 描述:

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

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

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

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

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

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

 

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

        因此生成的代码可以调用方法,而开发人员可以决定是否实现方法。

        与分部类非常类似,分部方法使代码生成器创建的代码和开发人员创建的代码能够协同工作,而不会产生运行时开销。

        分部方法声明由两个部分组成:定义和实现。它们可以位于分部类的不同部分中,

        也可以位于同一部分中。如果不存在实现声明,则编译器将优化定义声明和对方法的所有调用。

 

        分部方法声明必须以上下文关键字 partial 开头,并且方法必须返回 void。

        分部方法可以有 ref 参数,但不能有 out 参数。

        分部方法为隐式 private 方法,因此不能为 virtual 方法。

        分部方法不能为 extern 方法,因为主体的存在确定了方法是在定义还是在实现。

        分部方法可以有 static 和 unsafe 修饰符。

        分部方法可以为泛型的。约束将放在定义分部方法声明上,但也可以选择重复放在实现声明上。

        参数和类型参数名称在实现声明和定义声明中不必相同。

        不能将委托转换为分部方法。         

   b. 示例:

     

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

 

namespace NetTest

{

    /*

    可以将类或结构、接口或方法的定义拆分到两个或多个源文件中。

    每个源文件包含类型或方法定义的一部分,

    编译应用程序时将把所有部分组合起来   

 

    partial 修饰符不可用于委托或枚举声明中。

 

    将从所有分部类型定义中对以下内容进行合并:

    XML 注释

    接口

    泛型类型参数属性

    类属性

    成员   

    */

    public partial interface Chicken

    {

        void run();

    };

 

    public partial interface Chicken

    {

        void walk();

    }

 

    public class smallChicken : Chicken

    {

        #region Chicken Members

 

        public void run()

        {

            Console.Out.WriteLine("small chicken run..");

        }

 

        public void walk()

        {

            Console.Out.WriteLine("small chicken walk");

        }

 

        #endregion

    }

 

    public partial class TestPartial

    {

        public void TestA() { Console.Out.WriteLine("TestA"); }

 

        // Definition

        partial void onNameChanged();

 

    }

 

    public partial class TestPartial

    {

        public void TestB() { Console.Out.WriteLine("TestB"); }

        // Implementation

                partial void onNameChanged()

        {

            Console.Out.WriteLine("partial method");

        }

 

    }

 

    public partial class TestpartialCall

    {

 

        public void Test()

        {

            TestPartial test = new TestPartial();

            test.TestA();

            test.TestB();

 

            Chicken smallChicken=new smallChicken();

            smallChicken.run();

            smallChicken.walk();

 

        }

    }

}

分享到:
评论

相关推荐

    C#继承公共接口

    总结起来,C#中的公共接口继承允许开发者定义一组通用操作,并强制类遵循这些操作的约定。通过实现接口,类可以具有多种行为,实现多态性,提高代码的灵活性和可重用性。接口继承和实现是C#面向对象编程的重要组成...

    C#继承,接口,多态的实现与区别

    在C#编程语言中,继承、接口和多态是面向对象编程的重要概念,它们共同构建了C#类体系的灵活性和可扩展性。下面将详细阐述这三个概念的实现方式、功能以及它们之间的区别。 首先,**继承(Inheritance)**是C#中类...

    c# 中抽象类和接口的学习

    在C#编程语言中,抽象类和接口是实现面向对象...总之,抽象类和接口都是C#中强大的工具,可以帮助你构建更加模块化、可维护和可扩展的代码。理解它们的区别和如何正确使用它们,对于成为一名优秀的C#程序员至关重要。

    c#接口的意义 学习心得 读书笔记 (彻底弄清楚接口,轻松使用接口)

    "c#接口的意义 学习心得 读书笔记" ...c#接口是一个非常重要的概念,理解和应用接口可以提高系统的聚合性、灵活性和可扩展性。通过本文,读者可以更好地理解c#接口的定义、特点、优点和应用,提高自己的编程能力。

    C# 扩展方法小结

    C# 扩展方法是一种创新的编程特性,首次在C# 3.0中引入,旨在提供了一种向现有类型添加新方法而不必使用继承或封装的技术。这种方式有助于增强代码的可读性和灵活性,同时避免了过度使用继承导致的问题。 在面向...

    Modern C#系列课程(4): C#中类的设计

    在这个"Modern C#系列课程(4):C#中类的设计"中,我们将深入探讨如何有效地构建和组织C#代码,以实现可维护、可扩展和易于理解的程序。 首先,类是面向对象编程的核心概念,它代表了现实世界中的实体或概念。在C#中...

    c#中的面向对象继承

    在实际开发中,利用C#的面向对象继承特性,我们可以设计出更加模块化、可维护和可扩展的代码结构。通过理解和熟练运用这些概念,开发者能够构建出符合业务需求、高效运行的.NET应用程序。在学习过程中,结合实例和...

    设计模式:基于C#的工程化实现及扩展(完整电子版)

    在C#中,我们可以利用面向对象的特性,如类、接口和继承,来实现这些设计模式。例如,单例模式确保一个类只有一个实例,并提供全局访问点,这在管理共享资源时非常有用。C#中的静态类和 sealed 关键字可以方便地实现...

    继承 多态 接口 C# .net教程讲解

    理解并熟练掌握继承、多态和接口,对于任何C#开发者来说都是至关重要的,它们是构建复杂、灵活和可扩展系统的基础。 为了深入学习这些概念,你可以从"05.用对象思考:继承、多态、接口"这个文件开始,它很可能包含...

    C# 语言规范 1.0 - 5.0

    - 引用参数(ref和out)改进:允许在方法签名中传递可变引用。 5. **C# 5.0**: - 异步编程模型(async/await):引入异步编程关键字,简化异步操作。 - 委托和事件改进:引入了任务完成事件(Task.Completed...

    C# ACCESS 数据库操作类

    总结来说,"C# ACCESS 数据库操作类"是一个用于简化C#程序中与Access数据库交互的自定义类,它通过封装ADO.NET组件提供了高效且易于使用的数据库操作接口。"AccessHelper.cs"文件包含了实现这些功能的源代码,是理解...

    C#调用api接口

    C#调用API接口 本文将详细介绍如何在C#中调用API函数获取系统信息。API函数是构筑Windows应用程序的基石,是Windows编程的必备利器。每一种Windows应用程序开发工具都提供了间接或直接调用了Windows API函数的方法...

    C#继承的应用.ppt

    C#是一种面向对象的编程语言,其中继承是核心概念之一,允许类之间共享属性和行为。在"C#继承的应用.ppt"中,主要探讨了C#中继承的使用,适合初学者学习。本节将深入讲解C#的继承机制。 首先,C#支持两种类型的继承...

    c#基础系列之ref和out的深入理解

    本文中说的Ref和Out都是引用传递,Ref的重点是把值传给调用方法,Out则是得到调用方法的值,类似于有返回类型的方法返回的值; 在使用两者时一定要注意一下两点,否则编译出现错误 a) ref 变量使用前要先声明同时要...

    c# http接口设计及调用demo

    在IT行业中,C#是一种广泛使用的编程语言,尤其在开发Windows应用程序、Web应用以及游戏等领域。在本示例中,我们将关注的是"C# HTTP接口设计及调用demo",这通常涉及到如何创建一个HTTP服务端接口,以及如何使用C#...

    C#射击类游戏:龙之战(源码)

    射击类游戏:龙之战 开发环境:VS2005 开发语言:C# 参考网络上流传的《勇者斗恶龙》游戏源码制作的一个射击类游戏,借用了《勇者斗恶龙》的游戏界面及部分源码。 整个游戏框架已基本完成,源码中采用了一些设计模式...

    C#编程几个典型实例

    接口在C#中是一种完全抽象的类型,它定义了一组方法的签名,但不包含任何实现。通过实现接口,类可以承诺提供这些方法的实现,这使得不同类之间可以共享相同的公共行为,即使它们之间没有继承关系。例如,我们可以...

    C# 操作MySQL数据库类

    C# 操作MySQL数据库类 非存储过程操作类,如果要用到存储过程的话,自已修改里面的代码,里面的存储过程被我注释了。 至于调用方法,应该不用我说下载者应该也懂得吧,如果是对C#一巧不通的初学者,不懂也不要怪我...

    一种用C++动态扩展C++程序的方法.pdf

    1. **C++类继承C#基类**:首先,通过托管C++实现一个适配器类,该类同时继承自C#的基类和C++类,以此达到让C++类间接地继承C#类的目的。这一步骤确保了C++类可以访问和使用C#类提供的服务。 2. **动态创建和调用...

    C# serialport 串口发送与接收数据操作类

    C# 串口发送与接收数据操作类详解 C# SerialPort 串口发送与接收数据操作类是指通过使用 C# 语言中的 SerialPort 类来实现串口的发送和接收数据操作。该类提供了完整的串口操作功能,包括串口的打开、关闭、发送...

Global site tag (gtag.js) - Google Analytics