[索引頁]
[×××]
精進不休 .net 4.0 (4) - c# 4.0 新特性之命名參數和可選參數, 動态綁定(dynamic), 泛型協變和逆變, countdownevent, barrier
作者:webabcd
介紹
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
{
void page_load() void page_load(object sender, eventargs e)
{
write("hello");
write("hello", "webabcd");
write("hello", p3: false, p2: "webabcd");
}
void write() 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)
*
public class dyanmicdemo
string hello() string hello(string name)
return "hello: " + name;
public string name { get; set; }
public string this[string value]
get
{
return value;
}
dynamic getnames() dynamic getnames()
list<string> names = new list<string>() { "web", "webabc", "webabcd" };
return names;
public partial class dynamicbinding : system.web.ui.page
dynamic d = new dyanmicdemo();
response.write(d.hello("method"));
d.name = "hello: property";
response.write(d.name);
response.write(d["hello: indexer"]);
response.write(d.getnames().count.tostring());
// 注意:下面這句會報錯,因為不支援擴充方法
// response.write(d.getnames().last());
hello: method
hello: property
hello: indexer
3
3、泛型的協變的 demo
covariance.aspx.cs
泛型協變規則:
泛型參數受 out 關鍵字限制,隐式轉換目标的泛型參數類型必須是目前類型的“基類”
public partial class covariance : system.web.ui.page
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 關鍵字限制,隐式轉換目标的泛型參數類型必須是目前類型的“子類”
public partial class contravariance : system.web.ui.page
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
void write() void write(t o)
httpcontext.current.response.write(o.name);
webabcd
5、countdownevent 的 demo
countdowneventdemo.aspx.cs
* countdownevent - 線程、任務同步類。線程或任務一直阻塞到 countdownevent 的計數為 0 為止
* 1、當有新的需要同步的線程或任務産生時,就調用 addcount 增加 countdownevent 的計數
* 2、當有線程或任務到達同步點時,就調用 signal 函數減小 countdownevent 的計數
* 3、當 countdownevent 的計數為 0 時,就表示所有需要同步的任務已經完成。通過 wait 來阻塞線程
using system.threading;
public partial class countdowneventdemo : system.web.ui.page
private string _result = "";
static readonly object objlock = new object() static readonly object objlock = new object();
// 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));
t2.start();
thread t3 = new thread(() => threadwork("ccc", timespan.fromseconds(3), countdown));
t3.start();
// 減少 1 個計數
countdown.signal();
// 阻塞目前線程,直到 countdownevent 的計數為零
countdown.wait();
response.write(_result);
void threadwork() 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 ,可以實作當指定的線程或任務數完成的時候取消阻塞
public partial class barrierdemo : system.web.ui.page
private barrier _barrier;
// 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);
void threadwork() void threadwork(string name, timespan sleeptime)
lock (objlock)
_result += "barrier之前:" + name + " " + datetime.now.tostring("hh:mm:ss");
_result += "<br />";
// 當指定數量的線程或任務完成後,同步這些線程或任務
_barrier.signalandwait();
_result += "barrier之後:" + name + " " + datetime.now.tostring("hh:mm:ss");
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
ok