operator
operator 關(guān)鍵字用于在類或結(jié)構(gòu)聲明中聲明運(yùn)算符。運(yùn)算符聲明可以采用下列四種形式之一:
-
public static result-type operator unary-operator ( op-type operand )
-
public static result-type operator binary-operator (
op-type operand,
op-type2 operand2
)
-
public static implicit operator conv-type-out ( conv-type-in operand )
-
public static explicit operator conv-type-out ( conv-type-in operand )
參數(shù):
- result-type 運(yùn)算符的結(jié)果類型,。
- unary-operator 下列運(yùn)算符之一:+ - ! ~ ++ — true false
- op-type 第一個(gè)(或唯一一個(gè))參數(shù)的類型,。
- operand 第一個(gè)(或唯一一個(gè))參數(shù)的名稱,。
- binary-operator 其中一個(gè):+ - * / % & | ^ << >> == != > < >= <=
- op-type2 第二個(gè)參數(shù)的類型。
- operand2 第二個(gè)參數(shù)的名稱,。
- conv-type-out 類型轉(zhuǎn)換運(yùn)算符的目標(biāo)類型,。
- conv-type-in 類型轉(zhuǎn)換運(yùn)算符的輸入類型,。
注意:
- 前兩種形式聲明了用戶定義的重載內(nèi)置運(yùn)算符的運(yùn)算符。并非所有內(nèi)置運(yùn)算符都可以被重載(請參見可重載的運(yùn)算符),。op-type 和 op-type2 中至少有一個(gè)必須是封閉類型(即運(yùn)算符所屬的類型,,或理解為自定義的類型),。例如,,這將防止重定義整數(shù)加法運(yùn)算符。
- 后兩種形式聲明了轉(zhuǎn)換運(yùn)算符,。conv-type-in 和 conv-type-out 中正好有一個(gè)必須是封閉類型(即,,轉(zhuǎn)換運(yùn)算符只能從它的封閉類型轉(zhuǎn)換為其他某個(gè)類型,或從其他某個(gè)類型轉(zhuǎn)換為它的封閉類型),。
- 運(yùn)算符只能采用值參數(shù),,不能采用 ref 或 out 參數(shù)。
- C# 要求成對重載比較運(yùn)算符,。如果重載了==,,則也必須重載!=,否則產(chǎn)生編譯錯(cuò)誤,。同時(shí),,比較運(yùn)算符必須返回bool類型的值,,這是與其他算術(shù)運(yùn)算符的根本區(qū)別。
- C# 不允許重載=運(yùn)算符,,但如果重載例如+運(yùn)算符,,編譯器會(huì)自動(dòng)使用+運(yùn)算符的重載來執(zhí)行+=運(yùn)算符的操作。
- 運(yùn)算符重載的其實(shí)就是函數(shù)重載,。首先通過指定的運(yùn)算表達(dá)式調(diào)用對應(yīng)的運(yùn)算符函數(shù),,然后再將運(yùn)算對象轉(zhuǎn)化為運(yùn)算符函數(shù)的實(shí)參,接著根據(jù)實(shí)參的類型來確定需要調(diào)用的函數(shù)的重載,,這個(gè)過程是由編譯器完成,。
- 任何運(yùn)算符聲明的前面都可以有一個(gè)可選的屬性(C# 編程指南)列表。
explicit
explicit 關(guān)鍵字用于聲明必須使用強(qiáng)制轉(zhuǎn)換來調(diào)用的用戶定義的類型轉(zhuǎn)換運(yùn)算符,。
static explicit operator target_type { source_type identifier }
參數(shù):
- target_type 目標(biāo)類型
- source_type 源類型,。
- identifier Something。
注意:
- 轉(zhuǎn)換運(yùn)算符將源類型轉(zhuǎn)換為目標(biāo)類型,。源類型提供轉(zhuǎn)換運(yùn)算符,。與隱式轉(zhuǎn)換不同,必須通過強(qiáng)制轉(zhuǎn)換的方式來調(diào)用顯式轉(zhuǎn)換運(yùn)算符,。如果轉(zhuǎn)換操作可能導(dǎo)致異?;騺G失信息,則應(yīng)將其標(biāo)記為 explicit,。這可以防止編譯器無提示地調(diào)用可能產(chǎn)生無法預(yù)見后果的轉(zhuǎn)換操作,。
implicit
implicit 關(guān)鍵字用于聲明隱式的用戶定義類型轉(zhuǎn)換運(yùn)算符。
static implicit operator target_type { source_type identifier }
注意:
- 隱式轉(zhuǎn)換可以通過消除不必要的類型轉(zhuǎn)換來提高源代碼的可讀性,。但是,,因?yàn)榭梢栽诔绦騿T未指定的情況下發(fā)生隱式轉(zhuǎn)換,因此必須注意防止令人不愉快的后果,。一般情況下,,隱式轉(zhuǎn)換運(yùn)算符應(yīng)當(dāng)從不引發(fā)異常并且從不丟失信息,以便可以在程序員不知曉的情況下安全使用它們,。如果轉(zhuǎn)換運(yùn)算符不能滿足那些條件,則應(yīng)將其標(biāo)記為 explicit,。
示例:
以下是一個(gè)綜合示例,,簡要展示用法。如要更具體細(xì)節(jié)的了解,,請參閱MSDN Library,。
// keywords_operator.cs // keywords_operator.cs
using System;
namespace Hunts.Keywords { // 定義一個(gè)人民幣結(jié)構(gòu)。數(shù)據(jù)類型轉(zhuǎn)換的語法對于結(jié)構(gòu)和類是一樣的 public struct RMB { // 注意:這些數(shù)的范圍可能不能滿足實(shí)際中的使用 public uint Yuan; public uint Jiao; public uint Fen;
public RMB(uint yuan, uint jiao, uint fen) { if (fen > 9) { jiao += fen / 10; fen = fen % 10; } if (jiao > 9) { yuan += jiao / 10; jiao = jiao % 10; } this.Yuan = yuan; this.Jiao = jiao; this.Fen = fen; }
public override string ToString() { return string.Format("¥{0}元{1}角{2}分", Yuan, Jiao, Fen); }
// 一些操作 public static RMB operator +(RMB rmb1, RMB rmb2) { return new RMB(rmb1.Yuan + rmb2.Yuan, rmb1.Jiao + rmb2.Jiao, rmb1.Fen + rmb2.Fen); }
public static implicit operator float(RMB rmb) { return rmb.Yuan + (rmb.Jiao/10.0f) + (rmb.Fen/100.00f); }
public static explicit operator RMB(float f) { uint yuan = (uint)f; uint jiao = (uint)((f - yuan) * 10); uint fen = (uint)(((f - yuan) * 100) % 10); return new RMB(yuan, jiao, fen); }
// more } class App { static void Main() { RMB r1, r2, r3, r4;
// 記得小學(xué)時(shí)的某次捐款,,我把口袋里藏好的一塊錢加6張一毛錢以及13個(gè)一分錢的硬幣都貢獻(xiàn)出去了:( r1 = new RMB(1, 6, 13); // 其實(shí)當(dāng)時(shí)其他人都已經(jīng)交過了,,他們總共交了: r2 = new RMB(46, 9, 3); // 那么加上我的就是: r3 = r1 + r2; Console.WriteLine("r3 = {0}", r3.ToString());
// 隱式轉(zhuǎn)換 float f = r3; Console.WriteLine("float f= {0}", f);
// 顯式轉(zhuǎn)換 r4 = (RMB)f; Console.WriteLine("r4 = {0}", r4.ToString()); //如果不進(jìn)行顯示轉(zhuǎn)換,將出現(xiàn)錯(cuò)誤 CS0266: 無法將類型“float”隱式轉(zhuǎn)換為“Hunts.Keywords.RMB”,。存在一個(gè)顯式轉(zhuǎn)換(是否缺少強(qiáng)制轉(zhuǎn)換?)
Console.Read(); } } }
/* 控制臺(tái)輸出: r3 = ¥48元6角6分 float f = 48.66 r4 = ¥48元6角5分 */
我們會(huì)發(fā)現(xiàn)r4結(jié)果少了一分錢!這是因?yàn)樵冢?/p>
uint fen = (uint)(((f - yuan) * 100) % 10);
這句中,,在將float轉(zhuǎn)換為uint時(shí)發(fā)生了圓整錯(cuò)誤(這與計(jì)算機(jī)以二進(jìn)制存儲(chǔ)有關(guān)),。解決這個(gè)錯(cuò)誤,我們可以使用System.Convert類中用于處理數(shù)字的靜態(tài)方法:
uint fen = Convert.ToUInt32(((f - yuan) * 100) % 10);
不過使用System.Convert處理會(huì)有些性能的損失,。
|