C#基础语法-以Cpp为参照
C#
-
foreach
//foreach int[] fibarray = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; foreach (int element in fibarray) { Console.WriteLine(element); } //计数器 int count = 0; foreach(int element in fibarray) { count += 1; Console.WriteLine("Element #{0}:{1}", count, element); } Console.WriteLine("Number of elements in the array:{0}", count);
-
输出参数out
class NumberManipulator { //按引用传递参数 public void swap(ref int x,ref int y) { int temp; temp = x; x = y; y = temp; } //按输出传递参数 /* 就像引用参数,输出参数的形参担当实参的别名。方法内对形参的任何改变,在方法执行完成后,通过实参变量都是可见的。 不同的是,输出参数的要求是: 在方法内部,输出参数在被读取之前必须被赋值。这意味着,参数的初始值是无关的,而且没有必要在方法调用之前为实参赋值; 在方法返回之前,方法内部的任何贯穿路径的可能路径,都必须为所有输出参数进行一次赋值。 */ public void getValue(out int x) { int temp = 5; x = temp; } static void Main(string[] args) { NumberManipulator n = new NumberManipulator(); int a = 100; int b = 200; Console.WriteLine("交换前,a={0},b={1}", a, b); n.swap(ref a, ref b); Console.WriteLine("交换后,a={0},b={1}", a, b); n.getValue(out a); Console.WriteLine("调用后a的值:{0}", a); } }
-
可空类型(Nullable)
- 单问号?:对int,double,bool等无法付志伟null的数据进行null赋值,意思是这个数据类型是Nullable类型
int? i=3; //等价于 Nullable <int> i = new NUllable<int>(3); int i;//默认值0 int? ii;//默认值null
- 双问号??:Null合并运算符。如果第一个操作数的值为 null,则运算符返回第二个操作数的值,否则返回第一个操作数的值。
using System; namespace CalculatorApplication { class NullablesAtShow { static void Main(string[] args) { double? num1 = null; double? num2 = 3.14157; double num3; num3 = num1 ?? 5.34; // num1 如果为空值则返回 5.34 Console.WriteLine("num3 的值: {0}", num3); num3 = num2 ?? 5.34; Console.WriteLine("num3 的值: {0}", num3); Console.ReadLine(); } } }
-
输入输出:System.Console.ReadLine(),System.Console.WriteLine();
-
结构体
- 结构可带有方法、字段、索引、属性、运算符方法和事件。
- 结构可定义构造函数,但不能定义析构函数。但是,您不能为结构定义无参构造函数。无参构造函数(默认)是自动定义的,且不能被改变。
- 与类不同,结构不能继承其他的结构或类。
- 结构不能作为其他结构或类的基础结构。
- 结构可实现一个或多个接口。
- 结构成员不能指定为 abstract、virtual 或 protected。
- 当您使用 New 操作符创建一个结构对象时,会调用适当的构造函数来创建结构。与类不同,结构可以不使用 New 操作符即可被实例化。
- 如果不使用 New 操作符,只有在所有的字段都被初始化之后,字段才被赋值,对象才被使用。
-
类VS结构体
- 类是引用类型,结构是值类型。
- 结构不支持继承。
- 结构不能声明默认的构造函数。
-
#define预处理器
-
Regex类 用于表示一个正则表达式
-
特性
- 特性(Attribute)是用于在运行时传递程序中各种元素(比如类、方法、结构、枚举、组件等)的行为信息的声明性标签。您可以通过使用特性向程序添加声明性信息。一个声明性标签是通过放置在它所应用的元素前面的方括号([ ])来描述的。
- 特性(Attribute)用于添加元数据,如编译器指令和注释、描述、方法、类等其他信息。.Net 框架提供了两种类型的特性:预定义特性和自定义特性。
-
预定义特性(Attribute)
- AttributeUsage
- Conditional
- Obsolete
-
索引器(Indexer):索引器(Indexer) 允许一个对象可以像数组一样使用下标的方式来访问。
当您为类定义一个索引器时,该类的行为就会像一个 虚拟数组(virtual array) 一样。您可以使用数组访问运算符 [ ] 来访问该类的的成员。
//一维索引器 element-type this[int index] { // get 访问器 get { // 返回 index 指定的值 } // set 访问器 set { // 设置 index 指定的值 } }
-
委托(Delegate):相当于函数指针。
delegate <return type> <delegate-name> <parameter list>
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
-
事件(Event):事件(Event) 基本上说是一个用户操作,如按键、点击、鼠标移动等等,或者是一些提示信息,如系统生成的通知。应用程序需要在事件发生时响应事件。例如,中断。
C# 中使用事件机制实现线程间的通信
- 发布器(publisher)
- 订阅器(subscriber)
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 not fire" ); Console.ReadKey(); /* 回车继续 */ } } public EventTest() { int n = 5; SetValue( n ); } public void SetValue( int n ) { if ( value != n ) { value = n; OnNumChanged(); } } } /***********订阅器类***********/ public class subscribEvent { public void printf() { Console.WriteLine( "event fire" ); Console.ReadKey(); /* 回车继续 */ } } /***********触发***********/ public class MainClass { public static void Main() { EventTest e = new EventTest(); /* 实例化对象,第一次没有触发事件 */ subscribEvent v = new subscribEvent(); /* 实例化对象 */ e.ChangeNum += new EventTest.NumManipulationHandler( v.printf ); /* 注册 */ e.SetValue( 7 ); e.SetValue( 11 ); } } } /* event not fire event fire event fire */
-
参数数组 params :可变长度参数
class Program { static int SumVals params int[] vals) { int sum=0; foreach (int bal in vals) { sum+=val; } return sum; } static void Main(String[] args) { int sum = SumVals(1,5,2,9,8); Console.WriteLine("Summed Values = {0}",sum); Console.ReadKey(); } }
-
ManualResetEvent
通知一个或多个正在等待的线程已经发生的事件,允许线程通过发信号互相通信,来控制线程是否可访问资源。
当一个线程开始一个活动(此活动必须完成后,其他线程才能开始)时,它调用Reset以将 ManualResetEvent 置于非终止状态。此线程可被视为控制 ManualResetEvent。调用 ManualResetEvent 上的WaitOne的线程将阻止,并等待信号。当控制线程完成活动时,它调用Set以发出等待线程可以继续进行的信号。并释放所有等待线程。
一旦它被终止,ManualResetEvent 将保持终止状态,直到它被手动重置。即对 WaitOne 的调用将立即返回。
开启后默认不关闭,需要手动关闭。
using System;
using System.Threading;
namespace ManualResetEventTest
{
class Program
{
static ManualResetEvent mre = new ManualResetEvent(true);
static ManualResetEvent mre = new ManualResetEvent(false);
static void Main(string[] args)
{
//Console.WriteLine("Start!");
Thread[] threads = new Thread[3];
//Console.WriteLine("New Thread Finished!");
for (int i = 0; i < 3; i++)
{
threads[i] = new Thread(ThreadRun);
threads[i].Start();
}
Console.WriteLine("Hello,World!");
}
static void ThreadRun()
{
int _threadID = 0;
while (true)
{
mre.WaitOne();
_threadID = Thread.CurrentThread.ManagedThreadId;
Console.WriteLine("current Tread is " + _threadID);
Thread.Sleep(TimeSpan.FromSeconds(2));
}
}
}
}
_mre初始化为false时,为非终止状态
_mre初始化为True时,为终止状态
终止状态时 WaitOne()允许线程访问下面的语句,非终止状态时不可以。
在非终止状态时想让线程继续执行和停下来,需要使用Set()和Reset()方法。
using System;
using System.Threading;
namespace ManualResetEventTest
{
class Program
{
static ManualResetEvent _mre = new ManualResetEvent(false);
static void Main(string[] args)
{
Console.WriteLine("输入1为Set() 开始运行");
Console.WriteLine("输入2为Reset() 暂停运行");
Thread[] _threads = new Thread[3];
for (int i = 0; i < 3; i++)
{
_threads[i] = new Thread(ThreadRun);
_threads[i].Start();
}
Console.WriteLine("Finish create threads!");
while (true)
{
Console.WriteLine("Ready to read!");
char c = Console.ReadLine()[0];
Console.WriteLine("Finish read!");
switch (c)
{
case '1':
Console.WriteLine("Ready to run!");
_mre.Set();
Console.WriteLine("开始运行");
break;
case '2':
Console.WriteLine("Ready to stop!");
_mre.Reset();
Console.WriteLine("暂停运行");
break;
default:
Console.WriteLine("default!");
break;
}
}
}
static void ThreadRun()
{
int _threadID = 0;
while (true)
{
_threadID = Thread.CurrentThread.ManagedThreadId;
Console.WriteLine("current Tread is " + _threadID);
Thread.Sleep(TimeSpan.FromSeconds(2));
_mre.WaitOne();
}
}
}
}
- WaitOne()
-
WaitOne(),Wait(int),Wait(timespan,bool)
int里面是毫秒,如果在规定时间内set则阻塞后继续运行,返回值为true;如果没有在规定时间内返回,则返回值为false下次运行时不会再走这一步。
using System; using System.Threading; namespace testmono { class WaitOne { static ManualResetEvent autoEvent = new ManualResetEvent(false); static void Main() { Console.WriteLine("Main starting."); ThreadPool.QueueUserWorkItem(new WaitCallback(WorkMethod), autoEvent); // Wait for work method to signal. while(!autoEvent.WaitOne(100)) { //Console.WriteLine("Work method signaled."); Console.WriteLine("Timed out waiting for work " + "method to signal."); } Console.WriteLine("Main ending."); } static void WorkMethod(object stateInfo) { Console.WriteLine("Work starting."); // Simulate time spent working. Thread.Sleep(new Random().Next(100, 2000)); // Signal that work is finished. Console.WriteLine("Work ending."); ((ManualResetEvent)stateInfo).Set(); } } }
- get set
C#的特殊用法,其实是控制访问权限,get可读,set可写。
- ThreadStrat 和 ParameterizedThreadStart
区别:委托定义的函数是否能接受参数,ThreadStart不可以,ParameterizedThreadStart可以接受一个参数。
但因为可以把多个参数封装到一个类中,所以相当于ParameterizedThreadStart可以接受多个参数。
using System;
using System.Threading;
class AddParams
{
public int a, b;
public AddParams(int numb1, int numb2)
{
a = numb1;
b = numb2;
Console.WriteLine("AddParams!");
}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("***** Adding with Thread objects *****");
Console.WriteLine("ID of thread in Main(){0}" ,Thread.CurrentThread.ManagedThreadId);
AddParams ap = new AddParams(10, 10);
//委托
Thread t = new Thread(new ParameterizedThreadStart(Add));
Thread.Sleep(200);
Console.WriteLine("t has been created");
t.Start(ap);
Console.ReadLine();
}
#region Add method
static void Add(object data)
{
if (data is AddParams)
{
Console.WriteLine("ID of thread in Main(): {0}" ,Thread.CurrentThread.ManagedThreadId);
AddParams ap = (AddParams)data;
Console.WriteLine("{0} + {1} is {2}",ap.a, ap.b, ap.a + ap.b);
}
}
#endregion
}