我並不是不聞不問![C#]

來源:互聯網
上載者:User

我並不是不聞不問![C#]

 

Written by Allen Lee

 

我在《我只負責轉換![C/C++]》一文從類型轉換的角度展示了C/C++對程式員的信任,那麼C#對程式員的信任程度又有多高呢?

我們先來看一段C#代碼:

// Code #01

public enum Alignment
{
    Left,
    Center,
    Right
}

class Program
{
    static void Main()
    {
        Alignment a = (Alignment)(-1);
        Console.WriteLine(a);

        a = 0;
        Console.WriteLine(a);

        a = (Alignment)(1);
        Console.WriteLine(a);

        a = (Alignment)(2);
        Console.WriteLine(a);

        a = (Alignment)(3);
        Console.WriteLine(a);
    }
}

// Output:
//
// -1
// Left
// Center
// Right
// 3

這段代碼能夠順利編譯並運行。從輸出結果中,我們可以看出C#不會妨礙你進行非預期的枚舉轉換。只是你必須對你的行為進行負責,如果你進行了非預期的轉換,你將得到非預期的輸出;相反,如果轉換是有意義的話,輸出也將是有意義的。另外,0是被自動轉換成對應的枚舉類型,不需要我們動手。

現在來看另一段C#代碼:

// Code #02

public enum Alignment : byte
{
    Left,
    Center,
    Right
}

class Program
{
    static void Main()
    {
        Alignment a = (Alignment)(-1);
        Console.WriteLine(a);
    }
}

這次,我們為Alignment指定了底層類型,編譯器不再不聞不問了,它拒絕編譯並留下這樣一句話:

error CS0221: Constant value '-1' cannot be converted to a 'Alignment' (use 'unchecked' syntax to override)

跟之前的不同,程式員不應該由於疏忽導致這種溢出,如果你是有意這樣做的,必須用unchecked文法明確告訴編譯器:

// Code #03
// See Code #02 for Alignment.

class Program
{
    static void Main(string[] args)
    {
        unchecked
        {
            Alignment a = (Alignment)(-1);
            Console.WriteLine(a); 
        }
    }
}

// Output:
//
// 255

這次編譯器就不抱怨了,不過,你也應該認真想一下,這種溢出轉換是否真的有必要呢?

那麼,這種溢出轉換在C++的國度又是怎樣一番景象呢?請先看下面的C++代碼:

// Code #04

#include string>
#include iostream>

enum _jb_prog_mode : unsigned short
{
    PROGRAM_ONE,
    PROGRAM_TWO
};

int _tmain(int argc, _TCHAR* argv[])
{
    // In C, the enum keyword is required
    // to declare a variable of type enumeration.
    // In C++, the enum keyword can be omitted.
    // The following expression is legal in C++ only.

    _jb_prog_mode e_prog_index = (_jb_prog_mode)(-1);

    std::cout  (unsigned short)e_prog_index  std::endl;

    return 0;
}

// Output:
//
// 65535

這段代碼能夠正常編譯並順利運行。從輸出結果中我們明顯看到溢出,但編譯器和運行時卻沒有半點鐘聲響。看來,C++對程式員的信任程度真的去到了巔峰之處。

請注意,ANSI C不允許我們指定枚舉的底層類型,所有枚舉的底層類型都是int。

接下來我們看看註冊表的讀取,假定註冊表有如下資訊:

[HKEY_LOCAL_MACHINE\SOFTWARE\Allen]
"Name"="Allen Lee"
"ID"=dword:00000584

然後我們來看看下面的C#代碼:

// Code #05

class Program
{
    static void Main(string[] args)
    {
        RegistryKey rk = Registry.LocalMachine.OpenSubKey("software\\Allen");

        object obj = rk.GetValue("Name");
        string nm = (string)obj;        // Convert_01
        // int nm = (int)obj;           // Convert_02
        Console.WriteLine(nm);

        obj = rk.GetValue("ID");
        int id = (int)obj;              // Convert_03
        // string id = (string)obj;     // Convert_04
        Console.WriteLine(id);
    }
}

// Output:
//
// Allen Lee
// 1412

上面這段代碼當然可以正常輸出正確的結果。如果我們分別把Convert_01和Convert_03替換為Convert_02和Convert_04呢?編譯器不會拒絕你的編譯請求,但運行時會毫不猶豫地拋出InvalidCastException,並指出無法進行指定的類型轉換。

那麼,C++在面對類似的情況又是如何應付的呢?有興趣的朋友可以參照《我只負責轉換![C/C++]》一文中給出的代碼片斷實驗一下,你將體會到C++對程式員是何等的信任!

結論?也正如本文的題目——

我並不是不聞不問!

與C/C++比起來,C#的確沒有那麼自由,然而,這些限制卻為我們帶來另一番的味道。究竟C#的這些限制是對我們的一種協助還是一種縛束呢?這就見仁見智了。

 

See also:

  • Allen Lee;《我只負責轉換![C/C++]》
  • Allen Lee;《關於枚舉的種種 (Enumeration FAQ) [C#, IL, BCL]》

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.