C#

views 1492 words

coding online: https://repl.it/

Monte Carlo in C

using System;

class MainClass {
  public static void Main (string[] args) {
      // Construct a random number generator that generates random number greater than or equal to 0.0, and less than 1.0
      Random rand = new Random();

      // Approximate pi to within 5 digits.
      double tolerance = 1e-5;

      double piApproximation = 0;
      int total = 0;
      int numInCircle = 0;
      double x, y; // Coordinates of the random point.

      // Generate random points until our approximation within the desired tolerance.
      while ( Math.Abs( Math.PI - piApproximation ) > tolerance )
      {
        x = rand.NextDouble();
        y = rand.NextDouble();
        if ( x * x + y * y <= 1.0 ) // Is the point in the circle?
        {
          ++numInCircle;
        }
        ++total;
        piApproximation = 4.0 * ( (double) numInCircle / (double) total );
      }

      Console.WriteLine();

      Console.WriteLine( "Pi calculated to within {0} digits with {1} random points.",
        -Math.Log10( tolerance ), total );
      Console.WriteLine( "Approximated Pi = {0}", piApproximation );
  }
}

方法/函数

调用方法/函数时, 有三种参数传递的方式:

  1. 按值传递参数(默认). 它复制参数的实际值给函数的形式参数,实参(实际传入函数的参数)和形参(实际函数使用的参数)使用的是两个不同内存中的值. (形参的值发生改变时,不会影响实参的值)
  2. 按引用传递参数. 复制参数的内存位置的引用给形式参数. 即当形参的值发生改变时,同时也改变实参的值.
  3. 按输出传递参数. 输出参数会把方法输出的数据赋给自己 (这样可以返回多个值, return只能返回一个值)

code

using System;
namespace CalculatorApplication
{
   class NumberManipulator
   {
      // public void swap(ref int x, ref int y)
      public void swap(int x, int y)
      // public void swap(out int x, out int y)
      {
         int temp;

         temp = x; /* 保存 x 的值 */
         x = y;    /* 把 y 赋值给 x */
         y = temp; /* 把 temp 赋值给 y */
       }
   
      static void Main(string[] args)
      {
         NumberManipulator n = new NumberManipulator();
         /* 局部变量定义 */
         int a = 100;
         int b = 200;

         Console.WriteLine("在交换之前,a 的值: {0}", a);
         Console.WriteLine("在交换之前,b 的值: {0}", b);

         /* 调用函数来交换值, 方式1, 交换后的值不变 */
         // n.swap(a, b);
         /* 调用函数来交换值, 方式2, 成功交换 */
         n.swap(ref a, ref b);
         /* 调用函数来交换值, 方式3 */
         // n.swap(out a, out b);

         Console.WriteLine("在交换之后,a 的值: {0}", a);
         Console.WriteLine("在交换之后,b 的值: {0}", b);
 
         Console.ReadLine();

      }
   }
}

可空类型 (Nullable)

一个特殊的数据类型. 例如,Nullable< Int32 >,读作”可空的 Int32”,可以被赋值为 -2,147,483,648 到 2,147,483,647 之间的任意值,也可以被赋值为 null 值.

int? num1 = null;
int? num2 = 45;

Null 合并运算符( ?? ):

int num3;
num3 = num1 ?? 5;  // print 5
num3 = num2 ?? 5;  // print 45

Array

初始化:

double[] balance = new double[10];

赋值:

balance[0] = 4500.0;

在声明数组的同时给数组赋值:

double[] balance = { 2340.0, 4523.69, 3421.0};

创建并初始化一个数组:

int [] marks = new int[5]  { 99,  98, 92, 97, 95};  // 5是数组大小, 可以省略

访问:

double salary = balance[9];

使用 foreach 循环:

int count = 0;
foreach (double i in balance){
    Console.WriteLine("Balance[{0}] = {1}", count,i);
    count ++;
}

多维数组:

int [,] a = int [3,4] = {  
 {0, 1, 2, 3} ,   /*  初始化索引号为 0 的行 */
 {4, 5, 6, 7} ,   /*  初始化索引号为 1 的行 */
 {8, 9, 10, 11}   /*  初始化索引号为 2 的行 */
};

访问多维数组:

int val = a[2,3];

交错数组(数组的数组):

int[][] scores = new int[2][]{new int[]{92,93,94},new int[]{85,66,87,88}};

访问交错数组:

int s = scores[0][0]

传递数组给函数:

code

using System;

namespace ArrayApplication
{
   class ParamArray
   {
      public int AddElements(params int[] arr)  // !!!!
      {
         int sum = 0;
         foreach (int i in arr)
         {
            sum += i;
         }
         return sum;
      }
   }
      
   class TestClass
   {
      static void Main(string[] args)
      {
         ParamArray app = new ParamArray();
         // int [] temp = new int[]{1000, 2, 3, 17, 50};
         // int sum = app.AddElements(temp);
         int sum = app.AddElements(512, 720, 250, 567, 889); // !!!

         Console.WriteLine("总和是: {0}", sum);
         Console.ReadKey();
      }
   }
}

params 关键字, 使调用数组为形参的方法时,既可以传递数组实参,也可以只传递一组数组

Array 类: https://www.w3cschool.cn/csharp/csharp-array-class.html

List VS ArrayList VS List

String

https://www.w3cschool.cn/csharp/csharp-string.html

Dictionary

DictionarymyDictionary=newDictionary();

2 2
3 4
属性/方法 说明
Comparer 获取用于确定字典中的键是否相等的 IEqualityComparer
Count 获取包含在 Dictionary中的键/值对的数目
Item 获取或设置与指定的键相关联的值
Keys 获取包含 Dictionary中的键的集合
Values 获取包含 Dictionary中的值的集合
Add() 将指定的键和值添加到字典中
Clear 从 Dictionary中移除所有的键和值
ContainsKey() 确定 Dictionary是否包含指定的键
ContainsValue 确定 Dictionary是否包含特定值
GetEnumerator 返回循环访问 Dictionary的枚举数
GetType 获取当前实例的 Type (从 Object 继承)
Remove() 从 Dictionary中移除所指定的键的值
ToString 返回表示当前 Object的 String (从 Object 继承)
TryGetValue 获取与指定的键相关联的值

https://www.w3cschool.cn/csharp/csharp-86c42por.html

Struct

使得一个单一变量可以存储各种数据类型的相关数据. 与类不同,结构可以不使用 New 操作符即可被实例化. 类是引用类型,结构是值类型; 结构不支持继承; 结构不能声明默认的构造函数;

struct Books
{
   public string title;
   public string author;
   public string subject;
   public int book_id;
};  
Books Book1;        /* 声明 Book1,类型为 Book */
/* book 1 赋值 */
Book1.title = "C Programming";
Book1.author = "Nuha Ali"; 
Book1.subject = "C Programming Tutorial";
Book1.book_id = 6495407;
/* Book1 读取 */
Console.WriteLine( "Book 1 title : {0}", Book1.title);
Console.WriteLine("Book 1 author : {0}", Book1.author);
Console.WriteLine("Book 1 subject : {0}", Book1.subject);
Console.WriteLine("Book 1 book_id :{0}", Book1.book_id);

Enum

一组命名整型常量.

enum Days { Sun, Mon, tue, Wed, thu, Fri, Sat };
int WeekdayStart = (int)Days.Mon;
Console.WriteLine("Monday: {0}", WeekdayStart);

Class

一个数据类型的蓝图.

code

using System;
namespace BoxApplication{
    class Box{
        public static int num; // 静态成员; 无论有多少个类的对象被创建,只会有一个该静态成员的副本
        private double length;
        private double breadth;
        private double height;
        /* 构造函数 */
        public Box(double len){
            Console.WriteLine("对象已创建");
            length = len;
        }
         /* 析构函数, 当类的对象超出范围时执行, 它不返回值,也不带任何参数
         用于在结束程序(比如关闭文件、释放内存等)之前释放资源
          */
        ~Box(){
            Console.WriteLine("对象已删除");
        }
        /* 成员函数和封装 */
        public void setLength(double len){
            length = len;
        }
        public void setBreadth(double bre){
            breadth = len;
        }
        public void setHeight(double hei){
            height = hei;
        }
        public double getVolume(){
            return length * breadth * height;
        }        
    }
}

继承

OOP feature. 允许根据一个类来定义另一个类,这使得创建和维护应用程序变得更容易. 同时也有利于重用代码和节省开发时间.

基类和派生类. 一个基类可以有多个直接派生类. 派生类会隐式获得基类的所有成员(所有变量跟函数, 除了其构造函数和终结器). 派生类因而可以重用基类中的代码,而无需重新实现, 也可以在派生类中添加更多成员.

code

//派生类
class Rectangle: Box{
  public int getArea(){ 
     return (length * height); 
  }
  public void Display(){
     Console.WriteLine("长度: {0}", length);
     Console.WriteLine("高度: {0}", height);
     Console.WriteLine("面积: {0}", GetArea());
  }
}

基类的初始化 - 父类对象应在子类对象创建之前被创建, 可以在成员初始化列表中进行父类的初始化:
code

class Tabletop : Rectangle{
  private double cost;
  public Tabletop(double l, double h) : base(l, h){ } // !!!!!!
  public double GetCost(){
     double cost;
     cost = GetArea() * 70;
     return cost;
  }
  public void Display(){
     base.Display();  // !!!!!!
     Console.WriteLine("成本: {0}", GetCost());
  }
}

C# 不支持多重继承. 但是, 可以使用接口来实现多重继承
code

using System;
namespace InheritanceApplication
{
   class Shape {
      public void setWidth(int w){
         width = w;
      }
      public void setHeight(int h){
         height = h;
      }
      protected int width;
      protected int height;
   }

   // 基类 PaintCost
   public interface PaintCost {
      int getCost(int area);
   }
   // 派生类
   class Rectangle : Shape, PaintCost{
      public int getArea(){
         return (width * height);
      }
      public int getCost(int area){
         return area * 70;
      }
   }
   class RectangleTester{
      static void Main(string[] args){
         Rectangle Rect = new Rectangle();
         int area;
         Rect.setWidth(5);
         Rect.setHeight(7);
         area = Rect.getArea();
         // 打印对象的面积
         Console.WriteLine("总面积: {0}",  Rect.getArea());
         Console.WriteLine("油漆总成本: ${0}" , Rect.getCost(area));
         Console.ReadKey();
      }
   }
}

多态性

意味着有多重形式 —> 一个接口, 多个功能. 可以是静态(函数的响应是在编译时发生的) 或 动态(函数的响应是在运行时发生的)的

两种技术来实现静态多态性, 分别为:

  • 函数重载
  • 运算符重载

函数重载 - 在同一个范围内对相同的函数名有多个定义 (函数的定义必须彼此不同, 可以是参数类型不同 或者参数个数不同):

code

using System;
namespace PolymorphismApplication
{
   class Printdata{
      void print(int i){
         Console.WriteLine("Printing int: {0}", i );
      }

      void print(double f){
         Console.WriteLine("Printing float: {0}" , f);
      }

      void print(string s){
         Console.WriteLine("Printing string: {0}", s);
      }
      void print(string s, string s1){
         Console.WriteLine("Printing string: {0} and {1}", s,s1);
      }
      static void Main(string[] args){
         Printdata p = new Printdata();
         // 调用 print 来打印整数
         p.print(5);
         // 调用 print 来打印浮点数
         p.print(500.263);
         // 调用 print 来打印字符串
         p.print("Hello C++");
         // 调用 print 来打印字符串
         p.print("Hello C++","Hello Charon");
         Console.ReadKey();
      }
   }
}

动态多态性 - 用关键字 abstract 创建抽象类,用于提供接口的部分类的实现.当一个派生类继承自该抽象类时,实现即完成. 抽象类包含抽象方法,抽象方法可被派生类实现. 有关抽象类的一些规则:

  • 不能创建一个抽象类的实例
  • 不能在一个抽象类外部声明一个抽象方法
  • 通过在类定义前面放置关键字 sealed,可以将类声明为密封类. 当一个类被声明为 sealed 时,它不能被继承.(抽象类不能被声明为 sealed)

code

using System;
namespace PolymorphismApplication
{
   abstract class Shape{
      public abstract int area();
   }
   class Rectangle:  Shape{
      private int length;
      private int width;
      public Rectangle( int a=0, int b=0){
         length = a;
         width = b;
      }
      public override int area (){  //!!!!
         Console.WriteLine("Rectangle 类的面积:");
         return (width * length); 
      }
   }

   class RectangleTester{
      static void Main(string[] args){
         Rectangle r = new Rectangle(10, 7);
         double a = r.area();
         Console.WriteLine("面积: {0}",a);
         Console.ReadKey();
      }
   }
}

虚方法 - 实现在继承类中一个定义在类中的函数. 动态多态性是通过 抽象类 和 虚方法 实现的.

接口

接口(interface)定义了所有类继承接口时应遵循的语法合同. 接口定义了语法合同 “是什么” 部分(属性、方法和事件), 派生类定义了语法合同 “怎么做” 部分(成员的定义). (接口提供了派生类应遵循的标准结构)

code

using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace InterfaceApplication{
    // 接口
   public interface ITransactions{
      // 接口成员
      void showTransaction();
      double getAmount();
   }
   
   public class Transaction : ITransactions {  // 继承接口
      private string tCode;
      private string date;
      private double amount;
      public Transaction(){
         tCode = " ";
         date = " ";
         amount = 0.0;
      }
      public Transaction(string c, string d, double a){
         tCode = c;
         date = d;
         amount = a;
      }
      // 必须实现接口的所有方法, 必须和接口的格式一致
      public double getAmount(){
         return amount;
      }
      // 必须实现接口的所有方法, 必须和接口的格式一致
      public void showTransaction(){
         Console.WriteLine("Transaction: {0}", tCode);
         Console.WriteLine("Date: {0}", date);
         Console.WriteLine("Amount: {0}", getAmount());

      }

   }
   class Tester{
      static void Main(string[] args){
         Transaction t1 = new Transaction("001", "8/10/2012", 78900.00);
         Transaction t2 = new Transaction("002", "9/10/2012", 451900.00);
         t1.showTransaction();
         t2.showTransaction();
         Console.ReadKey();
      }
   }
}

命名空间

命名空间(Namespace)的设计目的是为了提供一种让一组名称与其他名称分隔开的方式. 一个 namespace 是一系列的类.

using 关键字表明程序使用的是给定命名空间中的名称, 这样在使用的时候就不用在前面加上命名空间名称.

code

using System;
using first_space;

namespace first_space{
    class abc{
      public void func(){
         Console.WriteLine("Inside first_space");
      }
   }
}
namespace second_space{
   class efg{
      public void func(){
         Console.WriteLine("Inside second_space");
      }
   }
}   
class TestClass{
   static void Main(string[] args){
      abc fc = new abc();  // first_space用了using, 所以不需要指定命名空间中的名称
      second_space.efg sc = new efg(); // seconde_space没用using, 所以需要指定命名空间中的名称
      fc.func();
      sc.func();
      Console.ReadKey();
   }
}

异常处理

try, catch, finally, throw

code

using System;
namespace ErrorHandlingApplication
{
    class DivNumbers{
        int result;
        DivNumbers(){
            result = 0;
        }
        public void division(int num1, int num2){
            try{
                result = num1 / num2;
            }
            catch (DivideByZeroException e){
                Console.WriteLine("Exception caught: {0}", e);
            }
            finally{
                Console.WriteLine("Result: {0}", result);
            }

        }
        static void Main(string[] args){
            DivNumbers d = new DivNumbers();
            d.division(25, 0);
            temperature = Console.ReadLine();
            if(temperature == 0){
                throw (new TempIsZeroException("Zero Temperature found"));
            }
      
            Console.ReadKey();
        }
    }
}

bubble sort

code

int[] array = new int[*];
for (int i=0; i < array.Length; i++){
    for(int j = i+1; j < array.Length; j++){
        if (array[j] < array[i]){
            int temp = array[i];
            array[i] = array[j];
            array[j] = temp;
        }
    }
}