C# 4.0 新特性之命名參數和可選參數, 動態綁定(dynamic), 泛型協變和逆變, CountdownEvent, Barrier
介紹
C# 4.0 的新特性
* Named And Optional Arguments - 命名參數和可選參數
* Dynamic Binding - 動態綁定(dynamic 用於動態編程,其依賴於Dynamic Language Runtime)
* Covariance - 泛型的協變
* Contravariance - 泛型的逆變
* CountdownEvent - 線程、任務同步類。線程或任務一直阻塞到 CountdownEvent 的計數為 0 為止
* Barrier - 線程、任務同步類。其用來同步一個線程組或任務組中所有的線程或任務,先到達的線程或任務在此阻塞
示例
1、命名參數和可選參數的 Demo
NamedAndOptionalArguments.aspx.cs
代碼
/*
* 命名參數和可選參數
* 命名參數:調用方法時,可以不按位置傳遞參數,而是指定參數的命名來傳值
* 可選參數:聲明方法中的參數時,可以為其設置默認值,那麼在調用該方法時,這種可選參數是可以忽略的
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace CSharp
{
public partial class NamedAndOptionalArguments : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
Write("hello");
Write("hello", "webabcd");
Write("hello", p3: false, p2: "webabcd");
}
private void Write(string p1, string p2 = "p2", bool p3 = true)
{
Response.Write(string.Format("p1:{0}; p2:{1}; p3:{2}", p1, p2, p3.ToString()));
Response.Write("<br />");
}
}
}
/*
運行結果:
p1:hello; p2:p2; p3:True
p1:hello; p2:webabcd; p3:True
p1:hello; p2:webabcd; p3:False
*/
2、dynamic 的 Demo
DynamicBinding.aspx.cs
代碼
/*
* dynamic - 用於動態編程,其依賴於Dynamic Language Runtime(DLR)
*
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace CSharp
{
public class DyanmicDemo
{
public string Hello(string name)
{
return "hello: " + name;
}
public string Name { get; set; }
public string this[string value]
{
get
{
return value;
}
}
public dynamic GetNames()
{
List<string> names = new List<string>() { "web", "webabc", "webabcd" };
return names;
}
}
public partial class DynamicBinding : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
dynamic d = new DyanmicDemo();
Response.Write(d.Hello("method"));
Response.Write("<br />");
d.Name = "hello: property";
Response.Write(d.Name);
Response.Write("<br />");
Response.Write(d["hello: indexer"]);
Response.Write("<br />");
Response.Write(d.GetNames().Count.ToString());
// 注意:下面這句會報錯,因為不支持擴展方法
// Response.Write(d.GetNames().Last());
}
}
}
/*
運行結果:
hello: method
hello: property
hello: indexer
3
*/
3、泛型的協變的 Demo
Covariance.aspx.cs
代碼
/*
泛型協變規則:
泛型參數受 out 關鍵字約束,隱式轉換目標的泛型參數類型必須是當前類型的“基類”
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace CSharp
{
public partial class Covariance : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
List<Human> human = new List<Human>();
human.Add(new Human { Name = "aaa" });
human.Add(new Human { Name = "bbb" });
human.Add(new Human { Name = "ccc" });
List<Hero> hero = new List<Hero>();
hero.Add(new Hero { Name = "ddd", Story = "尿床" });
hero.Add(new Hero { Name = "eee", Story = "撒謊" });
hero.Add(new Hero { Name = "fff", Story = "打架" });
/*
* List<T> 實現了如下接口 IEnumerable<out T> ,所以可以實現協變
* public interface IEnumerable<out T> : IEnumerable
* {
* // Summary:
* // Returns an enumerator that iterates through the collection.
* //
* // Returns:
* // A System.Collections.Generic.IEnumerator<T> that can be used to iterate through
* // the collection.
* IEnumerator<T> GetEnumerator();
* }
*/
// Hero 的基類是 Human,所以 Hero 可以協變到 Human,所以下面的表達式成立
List<Human> list = human.Union(hero).ToList();
foreach (Human h in list)
{
Response.Write(h.Name);
Response.Write("<br />");
}
}
class Human
{
public string Name { get; set; }
}
class Hero : Human
{
public string Story { get; set; }
}
}
}
/*
運行結果:
aaa
bbb
ccc
ddd
eee
fff
*/
4、泛型的逆變的 Demo
Contravariance.aspx.cs
代碼
/*
泛型逆變規則:
泛型參數受 in 關鍵字約束,隱式轉換目標的泛型參數類型必須是當前類型的“子類”
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace CSharp
{
public partial class Contravariance : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
IOutput<Human> human = new Output<Human>();
// 因為 IOutput<in T> ,並且 Human 的子類是 Hero ,所以 IOutput<Human> 可以逆變到 IOutput<Hero>
IOutput<Hero> hero = human;
hero.Write(new Hero { Name = "webabcd" });
}
interface IOutput<in T>
{
void Write(T o);
}
class Output<T> : IOutput<T>
where T : Human
{
public void Write(T o)
{
HttpContext.Current.Response.Write(o.Name);
}
}
class Human
{
public string Name { get; set; }
}
class Hero : Human
{
public string Story { get; set; }
}
}
}
/*
運行結果:
webabcd
*/
5、CountdownEvent 的 Demo
CountdownEventDemo.aspx.cs
代碼
/*
* CountdownEvent - 線程、任務同步類。線程或任務一直阻塞到 CountdownEvent 的計數為 0 為止
* 1、當有新的需要同步的線程或任務產生時,就調用 AddCount 增加 CountdownEvent 的計數
* 2、當有線程或任務到達同步點時,就調用 Signal 函數減小 CountdownEvent 的計數
* 3、當 CountdownEvent 的計數為 0 時,就表示所有需要同步的任務已經完成。通過 Wait 來阻塞線程
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Threading;
namespace CSharp
{
public partial class CountdownEventDemo : System.Web.UI.Page
{
private string _result = "";
private static readonly object objLock = new object();
protected void Page_Load(object sender, EventArgs e)
{
// CountdownEvent(int initialCount) - 實例化一個 CountdownEvent
// int initialCount - 初始計數
using (var countdown = new CountdownEvent(1))
{
Thread t1 = new Thread(() => ThreadWork("aaa", TimeSpan.FromSeconds(1), countdown));
// 增加 1 個計數
countdown.AddCount();
t1.Start();
Thread t2 = new Thread(() => ThreadWork("bbb", TimeSpan.FromSeconds(2), countdown));
countdown.AddCount();
t2.Start();
Thread t3 = new Thread(() => ThreadWork("ccc", TimeSpan.FromSeconds(3), countdown));
countdown.AddCount();
t3.Start();
// 減少 1 個計數
countdown.Signal();
// 阻塞當前線程,直到 CountdownEvent 的計數為零
countdown.Wait();
}
Response.Write(_result);
}
private void ThreadWork(string name, TimeSpan sleepTime, CountdownEvent countdown)
{
Thread.Sleep(sleepTime);
_result += "hello: " + name + " " + DateTime.Now.ToString("HH:mm:ss");
_result += "<br />";
// 減少 1 個計數
countdown.Signal();
}
}
}
/*
運行結果:
hello: aaa 15:18:55
hello: bbb 15:18:56
hello: ccc 15:18:57
*/
6、Barrier 的 Demo
BarrierDemo.aspx.cs
代碼
/*
* Barrier - 線程、任務同步類。其用來同步一個線程組或任務組中所有的線程或任務,先到達的線程或任務在此阻塞
* 1、實例化 Barrier 指定其需要阻塞的線程或任務數
* 2、通過 SignalAndWait ,可以實現當指定的線程或任務數完成的時候取消阻塞
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Threading;
namespace CSharp
{
public partial class BarrierDemo : System.Web.UI.Page
{
private Barrier _barrier;
private string _result = "";
private static readonly object objLock = new object();
protected void Page_Load(object sender, EventArgs e)
{
// Barrier(int participantCount) - 實例化一個 Barrier
// int participantCount - 需要阻塞的相關線程或任務數
_barrier = new Barrier(2);
Thread t1 = new Thread(() => ThreadWork("aaa", TimeSpan.FromSeconds(1)));
t1.Start();
Thread t2 = new Thread(() => ThreadWork("bbb", TimeSpan.FromSeconds(2)));
t2.Start();
Thread t3 = new Thread(() => ThreadWork("ccc", TimeSpan.FromSeconds(3)));
t3.Start();
Thread.Sleep(5 * 1000);
Response.Write(_result);
}
private void ThreadWork(string name, TimeSpan sleepTime)
{
lock (objLock)
{
_result += "Barrier之前:" + name + " " + DateTime.Now.ToString ("HH:mm:ss");
_result += "<br />";
}
Thread.Sleep(sleepTime);
// 當指定數量的線程或任務完成後,同步這些線程或任務
_barrier.SignalAndWait();
lock (objLock)
{
_result += "Barrier之後:" + name + " " + DateTime.Now.ToString ("HH:mm:ss");
_result += "<br />";
}
}
}
}
/*
運行結果:
Barrier之前:aaa 17:38:01
Barrier之前:ccc 17:38:01
Barrier之前:bbb 17:38:01
Barrier之後:bbb 17:38:03
Barrier之後:aaa 17:38:03
*/