我并不是不闻不问![C#]

我并不是不闻不问![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:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值