問題描述 考慮這樣一個需求:畫布上的對象支持手勢操作,手勢操作模式有平移、縮放、旋轉,對象可以支持一種或多種手勢,如何定義這個手勢操作模式? 就像文件的許可權一樣,只讀、只寫、讀寫,手勢操作也可以這樣設計。將手勢操作模式定義為簡單的枚舉類型是不夠的,我們需要表示不同模式的組合,需要支持位運算,因此每個 ...
問題描述
考慮這樣一個需求:畫布上的對象支持手勢操作,手勢操作模式有平移、縮放、旋轉,對象可以支持一種或多種手勢,如何定義這個手勢操作模式?
就像文件的許可權一樣,只讀、只寫、讀寫,手勢操作也可以這樣設計。將手勢操作模式定義為簡單的枚舉類型是不夠的,我們需要表示不同模式的組合,需要支持位運算,因此每個枚舉成員應該是位欄位,即每個枚舉成員都應該是2的冪。這樣我們就可以使用&、|、^、~
運算符對模式進行邏輯運算。手勢操作模式定義如下:
public enum ManipulationModes
{
None = 0,
Translate = 2,
Rotate = 4,
Scale = 8,
}
此時會有一個問題,比如想表示平移旋轉時,結果如下:
static void Main()
{
ManipulationModes mode = ManipulationModes.Translate | ManipulationModes.Rotate;
Console.WriteLine(mode); // 輸出:6
}
我們期望像文件讀寫許可權一樣,列印結果能為Translate, Rotate,但列印輸出結果為6,與期望不符。而且6不是ManipulationModes的成員,無法表示ManipulationModes操作模式。
FlagsAttribute
.NET提供了FlagsAttribute特性,表示聲明為位欄位的枚舉類型,我們需要為ManipulationModes添加FlagsAttribute:
[Flags]
public enum ManipulationModes
{
None = 0,
Translate = 2,
Rotate = 4,
Scale = 8,
}
static void Main()
{
ManipulationModes mode = ManipulationModes.Translate | ManipulationModes.Rotate;
Console.WriteLine(mode); // 輸出:Translate, Rotate
}
這樣輸出結果就符合期望值了,經過邏輯運算的值仍然是ManipulationModes的基礎值。
邏輯運算
可以使用|
運算符表示組合模式,使用&
運算符判斷是否支持特定模式,
// 使用 | 表示組合模式
var operMode = ManipulationModes.Translate | ManipulationModes.Rotate;
var transScaleMode = ManipulationModes.Translate | ManipulationModes.Scale;
// 使用 & 判斷是否支持某種模式
Console.WriteLine($"operMode是否支持平移模式:{(operMode & ManipulationModes.Translate) == ManipulationModes.Translate}");
Console.WriteLine($"operMode是否支持平移、旋轉模式:{(operMode & transScaleMode) == transScaleMode}");
WPF ManipulationModes源碼
下述代碼為WPF ManipulationModes的源碼:
[Flags]
public enum ManipulationModes
{
None = 0x0000,
TranslateX = 0x0001,
TranslateY = 0x0002,
Translate = TranslateX | TranslateY,
Rotate = 0x0004,
Scale = 0x0008,
All = Translate | Rotate | Scale,
}