C#编译器是如何判定某个变量没有使用过的?

这是我们某个组员在编程过程中提出的疑问。因为这个编译错误很容易避免,所以我一直也没有仔细想过这个问题,直到看过他的代码后才意识到,此问题并不是那么简单的。

先看看这段代码:

ExpandedBlockStart.gif 代码
class  Program
{
    
static   void  Main( string [] args)
    {
        
byte [] buf  =   new   byte [ 1024 ];
        T t 
=   new  T();
        
string  str  =   " 1234 " ;
        
int  n  =   1234 ;
        
int ?  nn  =   1234 ;
        DateTime dt 
=  DateTime.Now;
        
object  o  =   1234 ;

        Console.WriteLine(
" finish " );
    }
}

class  T { }

 

你觉得这段代码里有几个变量没有使用过呢?

如果从程序员的角度来看,答案应该是所有变量都没有使用过。但编译器给出的结果却有点违反直觉:

变量“str”已赋值,但其值从未使用过
变量“n”已赋值,但其值从未使用过
变量“nn”已赋值,但其值从未使用过


奇怪的地方在于,虽然所有变量都是用同样的方式声明,但编译器却只认为其中一部分没有使用过。这是怎么回事呢?

我们一个一个来分析。首先看看数组,如果使用默认值的话,编译器给出的信息就不同了:

byte [] buf1  =   null ;      //  有警告
byte [] buf2  =   new   byte [ 1024 ];  //  没有警告



这个结果似乎表明,如果参数赋值为null,那么编译器并不会真的执行赋值,并且变量会当作没有使用过。用IL检查的结果也可以证明此说法:对第一行,编译器没有生成任何对应的语句;对第二条则使用了newattr指令来创建数组。


对于自定义的类:

T t1  =   null ;     //  有警告
T t2  =   new  T();  //  没有警告


这个结果应当是可以理解的(尽管可以理解,但我认为并不好,理由见后)。虽然我们并没有调用该类的任何方法,但是类的构造函数仍然可能执行某些操作,所以只要创建了一个类,编译器就会把它当作已经使用过的。

对于基本值类型,其表现和引用类型又有所不同,编译器并不把初始赋值当作对变量的使用:

int  n1  =   0 ;   //  有警告
int  n2  =   1234 //  有警告
int ?  n3  =   null //  有警告
int ?  n4  =   0 //  有警告
int ?  n5  =   1234 //  有警告


string从实现上来说应当算是引用类型,但表现上却更加类似于值类型,警告信息也和值类型相同。

对于稍微复杂一些的值类型,结果有点微妙:

DateTime dt1;    //  有警告
DateTime dt2  =   new  DateTime();   //  有警告
DateTime dt3  =   new  DateTime( 2009 , 1 , 1 );   //  没有警告
DateTime dt4  =  DateTime.Now;   //  没有警告


这个结果有一点是需要注意的。尽管DateTime的默认构造函数和带参构造函数从用户角度看同样是构造函数,但在编译器的角度来看却是不一样的。用IL反编译也可以看出,如果调用默认构造函数的话,那么编译器调用的是initobj指令,而对带参构造函数调用的则是call ctor指令。此外,尽管从程序员的角度来看赋值代码的格式是完全相同的,但编译器却会根据所赋的值不同而采取不同的构造策略,这也是比较违反直觉的。

最后的结论比较遗憾,那就是C#的编译警告并不足以给予程序员足够的保护,特别是对于数组:
byte[] buf = new byte[1024];
如果仅构造这样一个数组而没有使用的话,那么编译器并不会给予程序员任何警告信息。

另外一个问题也是值得考虑的,声明一个类而不使用任何方法,比如仅仅
T t = new T()
这是合理的行为吗?编译器应该为此发出警告吗?
我个人的看法是,从使用的角度来说,这是不合理的,应当尽量避免,编译器发现此用法的话应该提出警告。如果确实有需要的话,可以通过编译指令或Attribute的方法来特别声明来避免警告信息。然而C#编译器的行为却是不发出警告,这一点我是不认同的。当然,我也希望大家提出自己的想法。

转载于:https://www.cnblogs.com/shuhari/archive/2009/12/12/cs_var_not_used.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值