C#_05_高级教程_上

1. 上篇
C# 泛型 (OK)
C# 匿名方法 (OK)
C# 委托 (OK)
C# 集合 (OK)
C# 索引器 (OK)
C# 事件 (OK)
C# 属性 (OK)


2. 下篇
C# 特性
C# 反射
C# 不安全代码
C# 多线程

 

 

 

C# 泛型

 

泛型

泛型允许推迟类或方法中编程元素的数据类型规范的编写,直到实际在程序中使用它的时候再编写。换句话说,泛型允许编写一个可以与任何数据类型协作的类或方法。

你可以通过数据类型的替代参数来编写类或方法的规范。当编译器遇到类的构造函数或方法的函数调用时,它会生成代码来处理指定的数据类型。下面这个简单的示例将有助于理解这个概念:

using System;
using System.Collections.Generic;

namespace GenericApplication
{
   public class MyGenericArray<T>
   {
      private T[] array;
      public MyGenericArray(int size)
      {
         array = new T[size + 1];
      }

      public T getItem(int index)
      {
         return array[index];
      }

      public void setItem(int index, T value)
      {
         array[index] = value;
      }
   }

   class Tester
   {
      static void Main(string[] args)
      {

         // 声明一个整型数组
         MyGenericArray<int> intArray = new MyGenericArray<int>(5);

         // 设置值
         for (int c = 0; c < 5; c++)
         {
            intArray.setItem(c, c*5);
         }

         // 获取值
         for (int c = 0; c < 5; c++)
         {
            Console.Write(intArray.getItem(c) + " ");
         }

         Console.WriteLine();

         // 声明一个字符数组
         MyGenericArray<char> charArray = new MyGenericArray<char>(5);

         // 设置值
         for (int c = 0; c < 5; c++)
         {
            charArray.setItem(c, (char)(c+97));
         }

         // 获取值
         for (int c = 0; c< 5; c++)
         {
            Console.Write(charArray.getItem(c) + " ");
         }
         Console.WriteLine();

         Console.ReadKey();
      }
   }
}

编译执行上述代码,得到如下结果:

0 5 10 15 20
a b c d e

泛型的特性

泛型是一种可以增强程序功能的技术,表现在如下几个方面:

  • 它有助于最大限度地进行重用代码、确保类型的安全以及提高性能。
  • 你可以创建泛型集合类。.NET 框架类库在 System.Collections.Generic 命名空间中包含了一些新的泛型集合类,你可以使用这些泛型集合类来替代 System.Collections 中的集合类。
  • 你可以创建自己的泛型接口、泛型类、泛型方法、泛型事件和泛型委托。
  • 你可以对泛型类进行约束,使其只访问具有特定数据类型的方法。
  • 在运行时,通过使用反射方法可以获取泛型数据类型中所使用的类型信息。

泛型方法

在之前的例子中,我们使用过一个泛型类,我们还可以通过类型参数来声明泛型方法。下述示例很好地展示了这个概念:

using System;
using System.Collections.Generic;

namespace GenericMethodAppl
{
   class Program
   {
      static void Swap<T>(ref T lhs, ref T rhs)
      {
         T temp;
         temp = lhs;
         lhs = rhs;
         rhs = temp;
      }
      static void Main(string[] args)
      {
         int a, b;
         char c, d;
         a = 10;
         b = 20;
         c = 'I';
         d = 'V';

         // 显示交换之前的值
         Console.WriteLine("Int values before calling swap:");
         Console.WriteLine("a = {0}, b = {1}", a, b);
         Console.WriteLine("Char values before calling swap:");
         Console.WriteLine("c = {0}, d = {1}", c, d);

         // 调用 swap 进行交换
         Swap<int>(ref a, ref b);
         Swap<char>(ref c, ref d);

         // 显示交换之后的值
         Console.WriteLine("Int values after calling swap:");
         Console.WriteLine("a = {0}, b = {1}", a, b);
         Console.WriteLine("Char values after calling swap:");
         Console.WriteLine("c = {0}, d = {1}", c, d);

         Console.ReadKey();
      }
   }
}

编译执行上述代码,得到如下结果:

Int values before calling swap:
a = 10, b = 20
Char values before calling swap:
c = I, d = V
Int values after calling swap:
a = 20, b = 10
Char values after calling swap:
c = V, d = I

泛型委托

你可以通过类型参数来定义一个泛型委托,如:

delegate T NumberChanger<T>(T n);

泛型委托示例:

using System;
using System.Collections.Generic;

delegate T NumberChanger<T>(T n);
namespace GenericDelegateAppl
{
   class TestDelegate
   {
      static int num = 10;
      public static int AddNum(int p)
      {
         num += p;
         return num;
      }

      public static int MultNum(int q)
      {
         num *= q;
         return num;
      }
      public static int getNum()
      {
         return num;
      }

      static void Main(string[] args)
      {
         // 创建委托实例
         NumberChanger<int> nc1 = new NumberChanger<int>(AddNum);
         NumberChanger<int> nc2 = new NumberChanger<int>(MultNum);

         // 使用委托对象调用方法
         nc1(25);
         Console.WriteLine("Value of Num: {0}", getNum());
         nc2(5);
         Console.WriteLine("Value of Num: {0}", getNum());
         Console.ReadKey();
      }
   }
}

编译执行以上代码,得到如下结果:

Value of Num: 35
Value of Num: 175

 

 

 

C# 匿名方法

 

匿名方法

先前的章节中提过,委托是用于引用与其具有相同签名的方法,即使用委托对象,就可以调用任何被该委托引用的方法。

匿名方法提供了一种将一段代码块作为委托参数的技术。顾名思义,匿名方法没有名字,只有方法主体。

你不需要为匿名方法指定返回类型,其返回类型直接由方法主体推断而来。

编写匿名方法

匿名方法通过使用 delegate 关键字创建委托实例来实现方法的声明,如:

delegate void NumberChanger(int n);
...
NumberChanger nc = delegate(int x)
{
   Console.WriteLine("Anonymous Method: {0}", x);
};

上述代码块中的 Console.WriteLine("Anonymous Method: {0}", x); 就是匿名方法的主体。

委托可以通过匿名方法调用,也可以通过命名方法调用,即,通过向委托对象来传递方法参数,如:

nc(10);

示例

using System;

delegate void NumberChanger(int n);
namespace DelegateAppl
{
   class TestDelegate
   {
      static int num = 10;
      public static void AddNum(int p)
      {
         num += p;
         Console.WriteLine("Named Method: {0}", num);
      }

      public static void MultNum(int q)
      {
         num *= q;
         Console.WriteLine("Named Method: {0}", num);
      }

      public static int getNum()
      {
         return num;
      }
      static void Main(string[] args)
      {
         //使用匿名方法创建委托实例
         NumberChanger nc = delegate(int x)
         {
            Console.WriteLine("Anonymous Method: {0}", x);
         };

         //使用匿名方法调用委托 
         nc(10);

         //使用命名方法实例化委托
         nc =  new NumberChanger(AddNum);

         //使用命名方法调用委托
         nc(5);

         //使用另一个命名方法实例化委托
         nc =  new NumberChanger(MultNum);

         //使用另一个命名方法调用委托
         nc(2);
         Console.ReadKey();
      }
   }
}

编译执行上述代码,得到如下结果:

Anonymous Method: 10
Named Method: 15
Named Method: 30

 

 

 

C# 委托

 

委托

C# 中的委托类似于 C 或 C++ 中指向函数的指针。委托表示引用某个方法的引用类型变量,运行时可以更改引用对象。

特别地,委托可以用于处理事件或回调函数。并且,所有的委托类都是从 System.Delegate 类继承而来。

声明委托

声明委托时,需要定义能够被委托所引用的方法,任意委托可以引用与该委托拥有相同签名的方法。如:

public delegate int MyDelegate (string s);

上述委托可以用于引用任何一个以字符型为参数的方法,且返回值类型为整型。

声明委托的句法规则为:

delegate <return type> <delegate-name> <parameter list>

实例化委托

声明委托之后,必须使用 new 关键字和一个特定的方法来创建一个委托对象。创建时,传递到 new 语句的参数写法与方法调用相同,但是不带有参数,例如:

public delegate void printString(string s);
...
printString ps1 = new printString(WriteToScreen);
printString ps2 = new printString(WriteToFile);

下述示例演示了委托的声明、实例化,此处的委托用于引用一个带有一个整型参数的方法,且该方法返回一个整型值。

using System;

delegate int NumberChanger(int n);
namespace DelegateAppl
{
   class TestDelegate
   {
      static int num = 10;
      public static int AddNum(int p)
      {
         num += p;
         return num;
      }

      public static int MultNum(int q)
      {
         num *= q;
         return num;
      }
      public static int getNum()
      {
         return num;
      }

      static void Main(string[] args)
      {
         // 创建委托实例
         NumberChanger nc1 = new NumberChanger(AddNum);
         NumberChanger nc2 = new NumberChanger(MultNum);

         // 使用委托对象调用方法
         nc1(25);
         Console.WriteLine("Value of Num: {0}", getNum());
         nc2(5);
         Console.WriteLine("Value of Num: {0}", getNum());
         Console.ReadKey();
      }
   }
}

编译执行上述代码,得到如下结果:

Value of Num: 35
Value of Num: 175

委托的多播

委托对象可通过 "+" 运算符进行合并。一个合并委托可以调用它所合并的两个委托,但只有相同类型的委托可被合并。"-" 运算符则可用于从合并的委托中移除其中一个委托。

利用委托的这种特性,可以创建一个委托被调用时所涉及的方法的调用列表。这被称为委托的多播,也叫组播。下面的程序演示了委托的多播:

using System;

delegate int NumberChanger(int n);
namespace DelegateAppl
{
   class TestDelegate
   {
      static int num = 10;
      public static int AddNum(int p)
      {
         num += p;
         return num;
      }

      public static int MultNum(int q)
      {
         num *= q;
         return num;
      }

      public static int getNum()
      {
         return num;
      }

      static void Main(string[] args)
      {
         // 创建委托实例
         NumberChanger nc;
         NumberChanger nc1 = new NumberChanger(AddNum);
         NumberChanger nc2 = new NumberChanger(MultNum);
         nc = nc1;
         nc += nc2;

         // 调用多播
         nc(5);
         Console.WriteLine("Value of Num: {0}", getNum());
         Console.ReadKey();
      }
   }
}

编译执行上述代码,得到如下结果:

Value of Num: 75

委托的使用

下面的示例演示了委托的作用,示例中的 printString 委托可用于引用带有一个字符串作为输入的方法,且不返回数据。

我们使用这个委托来调用两个方法,第一个方法将字符串输出到控制台,第二个方法将字符串输出到文件:

using System;
using System.IO;

namespace DelegateAppl
{
   class PrintString
   {
      static FileStream fs;
      static StreamWriter sw;

      // 委托声明
      public delegate void printString(string s);

      // 该方法打印到控制台
      public static void WriteToScreen(string str)
      {
         Console.WriteLine("The String is: {0}", str);
      }

      // 该方法打印到文件
      public static void WriteToFile(string s)
      {
         fs = new FileStream("c:\\message.txt",
         FileMode.Append, FileAccess.Write);
         sw = new StreamWriter(fs);
         sw.WriteLine(s);
         sw.Flush();
         sw.Close();
         fs.Close();
      }

      // 该方法把委托作为参数,并使用它调用方法
      // call the methods as required
      public static void sendString(printString ps)
      {
         ps("Hello World");
      }
      static void Main(string[] args)
      {
         printString ps1 = new printString(WriteToScreen);
         printString ps2 = new printString(WriteToFile);
         sendString(ps1);
         sendString(ps2);
         Console.ReadKey();
      }
   }
}

编译执行上述代码,得到如下结果:

The String is: Hello World

 

 

 

C# 集合

 

集合

集合类专门用于数据存储和数据检索,并提供堆栈、队列、列表和哈希表的支持。目前,大多数集合类都实现了相同的接口。

集合类服务于不同的目的,如为元素动态分配内存,基于索引访问列表项等等,这些类所创建的是 Object 类的对象的集合。在 C# 中,Object 类是所有数据类型的基类。

各种集合类及其用法

下表为一些常用的以 System.Collection 为命名空间的集合类,点击相应链接,可查看详细说明。

描述及用法
动态数组动态数组表示可被单独索引的对象的有序集合。
动态数组基本上可以替代数组,但与数组不同的是,通过索引,动态数组可以在指定的位置添加和移除项目,且会自动重新调整大小,同样允许在列表中进行动态内存分配、增加、搜索、排序各项。
哈希表哈希表使用来访问集合中的元素。
当需要通过键访问元素时,则使用哈希表,且一个有用的键值可以很方便地被识别。哈希表中的每一项都有一个键/值对。键用于访问集合中的项目。
排序列表排序列表使用索引来访问列表中的项。
它是数组和哈希表的组合,包含一个可使用键或索引访问各项的列表。若使用索引来访问各项,则它为一个动态数组,若使用键来访问各项,则它为一个哈希表。集合中的各项总是按键值排序。
堆栈堆栈表示的是一个后进先出的对象集合。
当需要对各项进行后进先出的访问时,则使用堆栈。在列表中添加一项,称为推入元素;从列表中移除一项时,称为弹出元素。
队列队列表示的是一个先进先出的对象集合。
当需要对各项进行先进先出的访问时,则使用队列。在列表中添加一项,称为入队;从列表中移除一项,称为出队
点阵列点阵列表示的是一个使用值 1 和 0 来表示的二进制数组
当需要存储位,但事先不知道位数时,则使用点阵列。通过整型索引,可以从点阵列集合中访问各项,该索引值从零开始。

 

 

 

 

 

C# 索引器

 

索引器

创建索引器可以使一个对象像数组一样被索引。为类定义索引器时,该类的行为类似于一个虚拟数组,使用数组访问运算符([ ])则可以对该类来进行访问。

句法规则

创建一个一维索引器的规则如下:

element-type this[int index]
{
   // get 访问器
   get
   {
      // 返回 index 指定的值
   }

   // set 访问器
   set
   {
      // 设置 index 指定的值
   }
}

使用索引器

索引器的声明在某种程度上类似于属性的声明,例如,使用 get 和 set 方法来定义一个索引器。不同的是,属性值的定义要求返回或设置一个特定的数据成员,而索引器的定义要求返回或设置的是某个对象实例的一个值,即索引器将实例数据切分成许多部分,然后通过一些方法去索引、获取或是设置每个部分。

定义属性需要提供属性名,而定义索引器需要提供一个指向对象实例的 this 关键字。

示例:

using System;
namespace IndexerApplication
{
   class IndexedNames
   {
      private string[] namelist = new string[size];
      static public int size = 10;
      public IndexedNames()
      {
         for (int i = 0; i < size; i++)
         namelist[i] = "N. A.";
      }

      public string this[int index]
      {
         get
         {
            string tmp;

            if( index >= 0 && index <= size-1 )
            {
               tmp = namelist[index];
            }
            else
            {
               tmp = "";
            }

            return ( tmp );
         }
         set
         {
            if( index >= 0 && index <= size-1 )
            {
               namelist[index] = value;
            }
         }
      }

      static void Main(string[] args)
      {
         IndexedNames names = new IndexedNames();
         names[0] = "Zara";
         names[1] = "Riz";
         names[2] = "Nuha";
         names[3] = "Asif";
         names[4] = "Davinder";
         names[5] = "Sunil";
         names[6] = "Rubic";
         for ( int i = 0; i < IndexedNames.size; i++ )
         {
            Console.WriteLine(names[i]);
         }

         Console.ReadKey();
      }
   }
}

编译执行上述代码,得到如下结果:

Zara
Riz
Nuha
Asif
Davinder
Sunil
Rubic
N. A.
N. A.
N. A.

重载索引器

索引器允许重载,即允许使用多种不同类型的参数来声明索引器。索引值可以是整数,但也可以是其他的数据类型,如字符型。

重载索引器示例:

using System;
namespace IndexerApplication
{
   class IndexedNames
   {
      private string[] namelist = new string[size];
      static public int size = 10;
      public IndexedNames()
      {
         for (int i = 0; i < size; i++)
         {
            namelist[i] = "N. A.";
         }
      }

      public string this[int index]
      {
         get
         {
            string tmp;

            if( index >= 0 && index <= size-1 )
            {
               tmp = namelist[index];
            }
            else
            {
               tmp = "";
            }

            return ( tmp );
         }
         set
         {
            if( index >= 0 && index <= size-1 )
            {
               namelist[index] = value;
            }
         }
      }
      public int this[string name]
      {
         get
         {
            int index = 0;
            while(index < size)
            {
               if (namelist[index] == name)
               {
                return index;
               }
               index++;
            }
            return index;
         }

      }

      static void Main(string[] args)
      {
         IndexedNames names = new IndexedNames();
         names[0] = "Zara";
         names[1] = "Riz";
         names[2] = "Nuha";
         names[3] = "Asif";
         names[4] = "Davinder";
         names[5] = "Sunil";
         names[6] = "Rubic";

         // 使用带有 int 参数的第一个索引器
         for (int i = 0; i < IndexedNames.size; i++)
         {
            Console.WriteLine(names[i]);
         }

         // 使用带有 string 参数的第二个索引器
         Console.WriteLine(names["Nuha"]);
         Console.ReadKey();
      }
   }
}

编译执行上述代码,得到如下结果:

Zara
Riz
Nuha
Asif
Davinder
Sunil
Rubic
N. A.
N. A.
N. A.
2

 

 

 

C# 事件

 

事件

事件指一个用户操作,如按键、点击、移动鼠标等,也可以是系统生成的通知。当事件发生时,应用需要对其作出相应的反应,如中断。另外,事件也用于内部进程通信。

通过事件使用委托

事件生成于类的声明中,通过使用同一个类或其他类中的委托与事件处理程序关联。包含事件的类用于发布事件,称为发布器类。其他接受该事件的类称为订阅器类。事件使用的是发布-订阅(publisher-subscriber)模型。

发布器是一个定义了事件和委托的对象,此外还定义了事件和委托之间的联系。一个发布器类的对象调用这个事件,同时通知其他的对象。

订阅器是一个接受事件并提供事件处理程序的对象。在发布器类中的委托调用订阅器类中的方法(或事件处理程序)。

声明事件

在类中声明一个事件,首先需要声明该事件对应的委托类型。如:

public delegate void BoilerLogHandler(string status);

其次为使用 event 关键字来声明这个事件:

//基于上述委托定义事件
public event BoilerLogHandler BoilerEventLog;

上述代码段定义了一个名为 BoilerLogHandler 的委托以及一个名为 BoilerEventLog 的事件,该事件生成时会自动调用委托。

示例 1

using System;
namespace SimpleEvent
{
   using System;

   public class EventTest
   {
      private int value;
      public delegate void NumManipulationHandler();
      public event NumManipulationHandler ChangeNum;
      protected virtual void OnNumChanged()
      {
         if (ChangeNum != null)
         {
            ChangeNum();
         }
         else
         {
            Console.WriteLine("Event fired!");
         }
      }

      public EventTest(int n )
      {
         SetValue(n);
      }

      public void SetValue(int n)
      {
         if (value != n)
         {
            value = n;
            OnNumChanged();
         }
      }
   }

   public class MainClass
   {
      public static void Main()
      {
         EventTest e = new EventTest(5);
         e.SetValue(7);
         e.SetValue(11);
         Console.ReadKey();
      }
   }
}

编译执行上述代码,得到如下结果:

Event Fired!
Event Fired!
Event Fired!

示例 2

该示例为一个简单的应用程序,该程序用于热水锅炉系统故障排除。当维修工程师检查锅炉时,锅炉的温度、压力以及工程师所写的备注都会被自动记录到一个日志文件中。

using System;
using System.IO;

namespace BoilerEventAppl
{
   // boiler 类
   class Boiler
   {
      private int temp;
      private int pressure;
      public Boiler(int t, int p)
      {
         temp = t;
         pressure = p;
      }

      public int getTemp()
      {
         return temp;
      }

      public int getPressure()
      {
         return pressure;
      }
   }

   // 事件发布器
   class DelegateBoilerEvent
   {
      public delegate void BoilerLogHandler(string status);

      // 基于上述委托定义事件
      public event BoilerLogHandler BoilerEventLog;

      public void LogProcess()
      {
         string remarks = "O. K";
         Boiler b = new Boiler(100, 12);
         int t = b.getTemp();
         int p = b.getPressure();
         if(t > 150 || t < 80 || p < 12 || p > 15)
         {
            remarks = "Need Maintenance";
         }
         OnBoilerEventLog("Logging Info:\n");
         OnBoilerEventLog("Temparature " + t + "\nPressure: " + p);
         OnBoilerEventLog("\nMessage: " + remarks);
      }

      protected void OnBoilerEventLog(string message)
      {
         if (BoilerEventLog != null)
         {
            BoilerEventLog(message);
         }
      }
   }

   // 该类保留写入日志文件的条款
   class BoilerInfoLogger
   {
      FileStream fs;
      StreamWriter sw;
      public BoilerInfoLogger(string filename)
      {
         fs = new FileStream(filename, FileMode.Append, FileAccess.Write);
         sw = new StreamWriter(fs);
      }

      public void Logger(string info)
      {
         sw.WriteLine(info);
      }

      public void Close()
      {
         sw.Close();
         fs.Close();
      }
   }

   // 事件订阅器
   public class RecordBoilerInfo
   {
      static void Logger(string info)
      {
         Console.WriteLine(info);
      }//end of Logger

      static void Main(string[] args)
      {
         BoilerInfoLogger filelog = new BoilerInfoLogger("e:\\boiler.txt");
         DelegateBoilerEvent boilerEvent = new DelegateBoilerEvent();
         boilerEvent.BoilerEventLog += new 
         DelegateBoilerEvent.BoilerLogHandler(Logger);
         boilerEvent.BoilerEventLog += new 
         DelegateBoilerEvent.BoilerLogHandler(filelog.Logger);
         boilerEvent.LogProcess();
         Console.ReadLine();
         filelog.Close();
      }//end of main

   }//end of RecordBoilerInfo
}

编译执行上述代码,得到如下结果:

Logging info:

Temperature 100
Pressure 12

Message: O. K

 

 

 

 

C# 属性

 

属性

属性是类、结构体和接口的命名成员。类或结构体中的成员变量或方法称为域。属性是域的扩展,且可使用相同的语法来访问。它们使用访问器让私有域的值可被读写或操作。

属性不会确定存储位置。相反,它们具有可读写或计算它们值的访问器。

例如,有一个名为 Student 的类,带有 age、name 和 code 的私有域。我们不能在类的范围以外直接访问这些域,但是我们可以拥有访问这些私有域的属性。

访问器

属性的访问器包含有助于获取(读取或计算)或设置(写入)属性的可执行语句。访问器声明可包含一个 get 访问器、一个 set 访问器,或者同时包含二者。例如:

    // 为字符类型声明一个叫 Code 的属性:
    public string Code
    {
        get
        {
            return code;
        }
        set
        {
            code = value;
        }
    }

    // 为字符类型声明一个叫 Name 的属性:
    public string Name
    {
        get
        {
            return name;
        }
        set
        {
            name = value;
        }
    }

    // 为整形类型声明一个叫 Age 的属性:
    public int Age
    { 
        get
        {
            return age;
        }
        set
        {
            age = value;
        }
    }

示例

下面的程序说明了特性是如何使用的:

    using System;
    namespace tutorialspoint
    {
    class Student
    {
      private string code = "N.A";
      private string name = "not known";
      private int age = 0;

      // 为字符类型声明一个叫 Code 的属性:
      public string Code
      {
         get
         {
            return code;
         }
         set
         {
            code = value;
         }
      }

      // 为字符类型声明一个叫 Name 的属性:
      public string Name
      {
         get
         {
            return name;
         }
         set
         {
            name = value;
         }
      }

      // 为整形类型声明一个叫 Age 的属性:
      public int Age
      {
         get
         {
            return age;
         }
         set
         {
            age = value;
         }
      }
      public override string ToString()
      {
         return "Code = " + Code +", Name = " + Name + ", Age = " + Age;
      }
    }

    class ExampleDemo
    {
      public static void Main()
      {

         // 创建一个 Student 类的对象
         Student s = new Student();

         // 为 student 对象设置 code,name 和 age
         s.Code = "001";
         s.Name = "Zara";
         s.Age = 9;
         Console.WriteLine("Student Info: {0}", s);

         //为 age 加 1
         s.Age += 1;
         Console.WriteLine("Student Info: {0}", s);
         Console.ReadKey();
      }
    }
    }

编译执行上述代码,得到如下结果:

    Student Info: Code = 001, Name = Zara, Age = 9
    Student Info: Code = 001, Name = Zara, Age = 10

抽象属性

抽象类可拥有抽象属性,这些属性应在派生类中被实现。下面的程序说明了这点:

    using System;
    namespace tutorialspoint
    {
    public abstract class Person
    {
      public abstract string Name
      {
         get;
         set;
      }
      public abstract int Age
      {
         get;
         set;
      }
    }

    class Student : Person
    { 
      private string code = "N.A";
      private string name = "N.A";
      private int age = 0;

      // 为字符类型声明一个叫 Code 的属性:
      public string Code
      {
         get
         {
            return code;
         }
         set
         {
            code = value;
         }
      }

      // 为字符类型声明一个叫 Name 的属性:
      public override string Name
      {
         get
         {
            return name;
         }
         set
         {
            name = value;
         }
      }

      // 为整形类型声明一个叫 Age 的属性:
      public override int Age
      {
         get
         {
            return age;
         }
         set
         {
            age = value;
         }
      }
      public override string ToString()
      {
         return "Code = " + Code +", Name = " + Name + ", Age = " + Age;
      }
    }

    class ExampleDemo
    {
      public static void Main()
      {
         // 创建一个 Student 类的对象
         Student s = new Student();

         // 为 student 对象设置 code,name 和 age
         s.Code = "001";
         s.Name = "Zara";
         s.Age = 9;
         Console.WriteLine("Student Info:- {0}", s);

         //为age加1
         s.Age += 1;
         Console.WriteLine("Student Info:- {0}", s);
         Console.ReadKey();
      }
    }
    }

编译执行上述代码,得到如下结果:

    Student Info: Code = 001, Name = Zara, Age = 9
    Student Info: Code = 001, Name = Zara, Age = 10

 

 

 

github地址: 

代码汇总: 

using System;
using System.Collections.Generic;
using System.IO;

/*
C# 泛型 (OK)
C# 匿名方法 (OK)
C# 委托 (OK)
C# 集合 (OK)
C# 索引器 (OK)
C# 事件 (OK)
C# 属性 (OK)


C# 特性
C# 反射
C# 不安全代码
C# 多线程
*/

namespace cs_10
{
    class MainClass
    {
        public static void Main(string[] args)
        {
            if(0 == 1){
                // int array
                BeyondGenericArray<int> intArr = new BeyondGenericArray<int>(5);
                for (int i = 0; i < 6; i++){
                    intArr.setItem(i, i * 2);
                }
                for (int i = 0; i < 6; i++)
                {
                    Console.Write(intArr.getItem(i) + " ");
                }

                Console.WriteLine();
                // char array
                BeyondGenericArray<char> charArr = new BeyondGenericArray<char>(26);
                for (int i = 0; i < 26; i++){
                    charArr.setItem(i, (char)(i + 97));
                }
                for (int i = 0; i < 26; i++){
                    Console.Write(charArr.getItem(i) + " ");
                }
            }

            if(1 == 2){
                // 可以创建自己的泛型接口、泛型类、泛型方法、泛型事件和泛型委托
                int a1, a2;
                char c1, c2;
                a1 = 6;
                a2 = 7;
                c1 = 'a';
                c2 = 'z';
                // show before swap 
                Console.WriteLine("a={0},b={1},c={2},d={3}",a1,a2,c1,c2);
                Swap<int>(ref a1, ref a2);
                Swap<char>(ref c1, ref c2);
                Console.WriteLine("a={0},b={1},c={2},d={3}", a1, a2, c1, c2);
            }

            if (2 == 3) {
                // 创建委托实例
                NumberChangerDelegate<int> delegate1 = new NumberChangerDelegate<int>(AddNumFunc);
                NumberChangerDelegate<int> delegate2 = new NumberChangerDelegate<int>(MultNumFunc);
                Console.WriteLine($"initial num is : {getNum()}");

                // 使用委托对象调用方法
                delegate1(3);
                Console.WriteLine($"after add 3 , num is {getNum()}");
                delegate2(2);
                Console.WriteLine($"after multiply 2 , num is {getNum()}");

            }

            if (3 == 4)
            {
                Console.WriteLine("1");
                // 使用匿名方法创建委托实例 (right hand is anonymous method)
                NumberChangerDelegate2 delegate3 = delegate(int x){
                    Console.WriteLine("3");
                    Console.WriteLine($"In Anonymous Method: {x}");
                    return x;
                };
                Console.WriteLine("2");
                // 使用匿名方法调用委托 
                delegate3(3);


                Console.WriteLine($"initial num is : {getNum()}");
                // 普通方式 创建委托实例 (使用命名方法实例化委托)
                delegate3 = new NumberChangerDelegate2(AddNumFunc);
                // 使用命名方法调用委托
                delegate3(3);
                Console.WriteLine($"after add 3 , num is {getNum()}");


                // 普通方式 创建委托实例 (使用命名方法实例化委托)
                delegate3 = new NumberChangerDelegate2(MultNumFunc);
                delegate3(2);
                Console.WriteLine($"after multiply 2 , num is {getNum()}");
            }

            if (4 == 5){
                // 使用命名方法实例化委托
                NumberChangerDelegate2 delegate1 = new NumberChangerDelegate2(AddNumFunc);
                NumberChangerDelegate2 delegate2 = new NumberChangerDelegate2(MultNumFunc);
                Console.WriteLine($"initial num is : {getNum()}");

                // 使用委托对象调用方法
                delegate1(3);
                Console.WriteLine($"after add 3 , num is {getNum()}");
                delegate2(2);
                Console.WriteLine($"after multiply 2 , num is {getNum()}");
            }

            if (5 == 6) {
                // 多播,组播
                // 创建委托实例
                NumberChangerDelegate2 delegate4;
                NumberChangerDelegate2 delegateAdd = new NumberChangerDelegate2(AddNumFunc);
                NumberChangerDelegate2 delegateMult = new NumberChangerDelegate2(MultNumFunc);
                delegate4 = delegateAdd;
                // 委托对象可通过 "+" 运算符进行合并
                // 方法add执行完后,立即执行方法mult;相当于ios代理或block;相当于js中的callback;相当于java中listener或handler
                delegate4 += delegateMult;

                // 调用多播
                delegate4(3);
                Console.WriteLine($"after 多播, num is : {getNum()}");
            }

            if (6 == 7) {
                printStrDelegate delegate1 = new printStrDelegate(WriteToScreenFunc);
                printStrDelegate delegate2 = new printStrDelegate(WriteToFileFunc);
                sendStrFunc(delegate1);
                sendStrFunc(delegate2);
            }

            if (7 == 8){
                MainClass mainClass = new MainClass();
                mainClass[0] = "beyond";
                mainClass[1] = "mathilda";
                mainClass[2] = "menma";
                for (int i = 0; i < MainClass.size; i++){
                    Console.WriteLine(mainClass[i]);
                }
            }

            if (8 == 9)
            {
                MainClass mainClass = new MainClass();
                mainClass[0] = "beyond";
                mainClass[1] = "mathilda";
                mainClass[2] = "menma";
                // 带有 int 参数的第一个索引器
                for (int i = 0; i < MainClass.size; i++)
                {
                    Console.WriteLine(mainClass[i]);
                }
                // 带有 string 参数的第二个索引器
                Console.WriteLine(mainClass["mathilda"]);
            }

            if (9 == 10){
                MainClass mainClass = new MainClass(67);
                // 订阅事件
                mainClass.changeNumEvent += new NumManipulationEventHandler(displayFunc);
                mainClass.changeNumEvent += delegate () {
                    Console.WriteLine("anonymous methods as event handler");
                };
                mainClass.SetValue(5);
                mainClass.SetValue(20);
            }

            if (10 == 11) {
                Leader leader = new Leader();
                SoldierA a = new SoldierA(leader);
                SoldierB b = new SoldierB(leader);
                leader.RaiseCup("left");
                leader.RaiseCup("right");
                leader.BreakCup();
            }

            if (11 == 12)
            {
                BoilerFileLogger fileLog = new BoilerFileLogger("test.txt");
                BoilerEventPublisher eventPublisher = new BoilerEventPublisher();
                // 事件订阅
                eventPublisher.boilerLogEvent += new BoilerEventPublisher.BoilerLogEventHandler(MainClass.loggerFunc);
                eventPublisher.boilerLogEvent += new BoilerEventPublisher.BoilerLogEventHandler(fileLog.loggerFunc);

                // 手动触发事件
                eventPublisher.logProcess();
                fileLog.close();
            }

            if (12 == 13)
            {
                Student stu = new Student();
                stu.Code = "No.1";
                stu.Name = "Beyond";
                stu.Age = 18;
                Console.WriteLine("Student Info: {0}", stu);

                stu.Age += 12;
                Console.WriteLine("Student Info: {0}", stu);
            }

            if (13 == 13){
                Girl mathilda = new Girl();
                mathilda.Cup = "AA";
                mathilda.Age = 12;
                mathilda.Name = "玛蒂尔达";
                Console.WriteLine("The Girl is : {0}", mathilda);

                mathilda.Cup = "A";
                mathilda.Age += 1;
                Console.WriteLine("The Girl is : {0}", mathilda);
            }

        }

        // other static function ==============
        static void displayFunc(){
            Console.WriteLine("hello world");
        }
        static void Swap<T>(ref T leftHandSide, ref T rightHandSide){
            T temp;
            temp = leftHandSide;
            leftHandSide = rightHandSide;
            rightHandSide = temp;
        }


        // Generic delegate ==============
        delegate T NumberChangerDelegate<T>(T n);
        static int num = 67;
        public static int AddNumFunc(int otherNum){
            num += otherNum;
            return num;
        }

        public static int MultNumFunc(int otherNum){
            num *= otherNum;
            return num;
        }

        public static int getNum(){
            return num;
        }

        // common delegate ==============
        // 匿名方法通过使用 delegate 关键字创建委托实例来实现方法的声明
        delegate int NumberChangerDelegate2(int n);

        // other property ==============
        static FileStream fileStream;
        static StreamWriter streamWriter;
        delegate void printStrDelegate(string s);
        static void WriteToScreenFunc(string str){
            Console.WriteLine($"the string is : {str}");
        }
        static void WriteToFileFunc(string s){
            // ./bin/debug/test.txt
            fileStream = new FileStream("test.txt",FileMode.Append,FileAccess.Write);
            streamWriter = new StreamWriter(fileStream);
            streamWriter.WriteLine(s);
            streamWriter.Flush();
            streamWriter.Close();
            fileStream.Close();
        }
        // 该方法把委托作为参数,并使用它调用方法
        static void sendStrFunc(printStrDelegate psDelegate){
            psDelegate("Hello Beyond");
        }


        // other property for index ==============
        private string[] nameArr = new string[size];
        public static int size = 10;
        // constructor
        public MainClass(){
            for (int i = 0; i < size; i++){
                nameArr[i] = "N. A.";
            }
        }
        // 带有 int 参数的第一个索引器
        public string this[int index]{
            get{
                string tmpStr;
                if(index >= 0 && index < size){
                    tmpStr = nameArr[index];
                }else{
                    tmpStr = "";
                }
                return (tmpStr);
            }

            set{
                if(index >= 0 && index < size){
                    // value is default inputParam
                    nameArr[index] = value;
                }
            }
        }
        // 带有 string 参数的第二个索引器
        public int this[string girlName]{
            get{
                int index = 0;
                while(index < size){
                    if(nameArr[index] == girlName){
                        return index;
                    }
                    index++;
                }
                return index;
            }
        }


        // other property for event ==================
        private int value;
        // 在类中声明一个事件,首先需要声明该事件对应的委托类型
        public delegate void NumManipulationEventHandler();
        // 基于上述委托定义事件
        public event NumManipulationEventHandler changeNumEvent;
        protected virtual void OnNumChanged(){
            if(changeNumEvent != null){
                changeNumEvent();
            }else{
                Console.WriteLine("Event Fired");
            }
        }
        // constructor override
        public MainClass(int n){
            SetValue(n);
        }
        public void SetValue(int n){
            if(value != n){
                value = n;
                OnNumChanged();
            }
        }



        // other static methods ==================
        static void loggerFunc(string info){
            Console.WriteLine(info);
        }





    }



    // other class ==============
    class BeyondGenericArray<T>{
        private T[] array;
        // constructor
        public BeyondGenericArray(int size)
        {
            array = new T[size + 1];
        }
        public T getItem(int index){
            return array[index];
        }
        public void setItem(int index, T item){
            array[index] = item;
        }
            
    }

    // other class for event and delegate==============
    class Leader{
        // other property for event and delegate ==================
        public void RaiseCup(string handSide)
        {
            Console.WriteLine("首领{0}手举杯", handSide);
            if (raiseCupEvent != null)
            {
                raiseCupEvent(handSide);
            }
        }
        public void BreakCup()
        {
            Console.WriteLine("首领摔杯为号");
            if (breakCupEvent != null)
            {
                breakCupEvent();
            }
        }
        public delegate void RaiseCupEventHandler(string handSide);
        public delegate void BreakCupEventHandler();
        public event RaiseCupEventHandler raiseCupEvent;
        public event BreakCupEventHandler breakCupEvent;


    }
    class SoldierA{
        Leader leader;
        // constructor
        public SoldierA(Leader l){
            this.leader = l;
            leader.raiseCupEvent += new Leader.RaiseCupEventHandler(raiseCupEventHandlerFunction);
            leader.breakCupEvent += new Leader.BreakCupEventHandler(breakCupEventHandlerFunction);
        }
        public void raiseCupEventHandlerFunction(string handSide){
            if(handSide.Equals("left")){
                Attack();
            }
        }
        public void breakCupEventHandlerFunction(){
            Attack();
        }
        public void Attack(){
            Console.WriteLine("soldier A attack");
        }
    }
    class SoldierB
    {
        Leader leader;
        // constructor
        public SoldierB(Leader l)
        {
            this.leader = l;
            leader.raiseCupEvent += new Leader.RaiseCupEventHandler(raiseCupEventHandlerFunction);
            leader.breakCupEvent += new Leader.BreakCupEventHandler(breakCupEventHandlerFunction);
        }
        public void raiseCupEventHandlerFunction(string handSide)
        {
            if (handSide.Equals("right"))
            {
                Attack();
            }
        }
        public void breakCupEventHandlerFunction()
        {
            Attack();
        }
        public void Attack()
        {
            Console.WriteLine("soldier B attack");
        }
    }


    // other property for boiler event and delegate ==================
    class Boiler {
        private int temp;
        private int pressure;
        // constructor
        public Boiler(int t, int p)
        {
            this.temp = t;
            this.pressure = p;
        }
        public int getTemp()
        {
            return this.temp;
        }
        public int getPressure()
        {
            return this.pressure;
        }
    }

    // 事件发布器
    class BoilerEventPublisher{
        public delegate void BoilerLogEventHandler(string status);
        // 基于上述委托定义事件
        public event BoilerLogEventHandler boilerLogEvent;

        public void logProcess(){
            string remarks = "O.K";
            Boiler b = new Boiler(100, 12);
            int t = b.getTemp();
            int p = b.getPressure();
            if(t > 150 || t < 80 || p > 15 || p < 12){
                remarks = "Need Maintenance";
            }
            onBoilerLogEvent($"Logging Info: \t {DateTime.Now}\n");
            onBoilerLogEvent($"Temperature {t} \nPressure: {p}");
            onBoilerLogEvent($"\nMessage: {remarks}");
        }

        protected void onBoilerLogEvent(string message){
            if(boilerLogEvent != null){
                boilerLogEvent(message);
            }
        }
    }

    // 写入日志文件
    class BoilerFileLogger{
        FileStream fs;
        StreamWriter sw;
        public BoilerFileLogger(string filename){
            fs = new FileStream(filename, FileMode.Append, FileAccess.Write);
            sw = new StreamWriter(fs);
        }
        public void loggerFunc(string info){
            sw.WriteLine(info);
        }
        public void close(){
            sw.Close();
            fs.Close();
        }

    }



    // other class no 属性 with getter & setter ==================
    class Student {
        // field : code name & age
        private string code = "N.A";
        private string name = "not known";
        private int age = 0;
        // property Code Name & Age
        public string Code
        {
            get
            {
                return this.code;
            }
            set
            {
                this.code = value;
            }
        }
        public string Name
        {
            get
            {
                return this.name;
            }
            set
            {
                this.name = value;
            }
        }
        public int Age
        {
            get
            {
                return this.age;
            }
            set
            {
                this.age = value;
            }
        }
        public override string ToString()
        {
            return "Property Code = " + Code + ", Name = " + Name + ", Age = " + Age;
        }
    }

    // abstract class no 属性 with getter & setter ==================
    abstract class Person{
        // 抽象类可拥有抽象属性,这些属性应在派生类中被实现。
        public abstract string Name{
            get;
            set;
        }
        public abstract int Age{
            get;
            set;
        }
    }

    class Girl : Person {
        // field: cup & name & age
        private string cup = "N.A";
        private string name = "N.A";
        private int age = 0;

        // property: Cup & Name & Age
        // 声明一个叫 Cup 的属性(Property)
        public string Cup {
            get {
                return this.cup;
            }
            set{
                this.cup = value;
            }
        }
        public override string Name { 
            get => this.name; 
            set => this.name = value; 
        }
        public override int Age { 
            get => this.age; 
            set => this.age = value; 
        }
        public override string ToString()
        {
            return "Property Cup = " + Cup + ", Name = " + Name + ", Age = " + Age;
        }
    }



}

 

 

 

 

未完待续,下一章节,つづく

 

  • 16
    点赞
  • 71
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值