老兔新传IT版

穷困潦倒的IT公司职员的故事

  博客园 :: :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

我曾经遇到过一个项目,由一群菜鸟开发,项目中大量混用了公共字段和属性。事实上菜鸟们仅在只读属性上使用了属性,可读可写的属性全部使用了公共字段。我的Team接手了这个项目的维护工作后,一个兄弟告诉我要把所有的公共字段变成属性,并给出了非常充分的理由。当然,我们都认为这是绝对正确的选择,并且正好有时间来做这样一件大有脾益的事情,特别是在一堆将要长期维护的代码面前。
和日本客户沟通之后我们就着手开始了这样一场战斗,所有的公共字段都被一个个找出来进行评价,以决定他将变成一个怎么样的属性。
感谢上帝的是,那帮菜鸟在命名公共字段时采用了属性式的命名方式,所有首字母都是大写的。这样我们就不需要考虑属性的命名问题,可以非常轻松的进行工作——所有的公共字段都变成私有,将首字母变成小写并使用Visual Studio的功能自动添加属性。最后根据先前的评价对属性的访问器进行相应的编辑。一切都显得非常完美。

不过当我们将修改之后的编译版本自信满满的的交给客户后,客户告诉我们一个要让人大呼上帝的消息——系统崩溃了。而且貌似问题就出在那一堆修改后的属性上。我们整个Team的成员都进入了一个近乎崩溃的状态。“将公共字段变成属性后,名字都没变,怎么就会崩溃呢?
从客户传回的资料来看发生了一个MissingFieldException,缺失的字段名正是被我们修改后的属性名,我以人格担保拼写是没有问题的。

我想,为了更好的说明这个问题,我们不如来写几段短小的代码。
首先我们负责修改的那个项目,不如称为TestDll,TestDll中有一个名为Class1的Class,他有一个公共字段叫做HelloWorldString

namespace TestDll
{
    
public class Class1
    {
        
public string HelloWorldString = "Hello World!";
    }
}

然后呢,在客户那边有一个命令行工程名为TestHelloWorld;其中有一个类引用了我们DLL。他有如下一段引用的代码:

namespace TestHelloWorld
{
    
class Program
    {
        
static void Main(string[] args)
        {
            TestDll.Class1 testClass 
= new TestDll.Class1();
            Console.WriteLine(testClass.HelloWorldString);
        }
    }
}

上帝告诉我们以上两段代码的执行绝对是没有问题的,当我们团队接手后,将TestDll改成了这样:

namespace TestDll
{
    
public class Class1
    {
        
//public string HelloWorldString = "Hello World!";

        
private string helloWorldString = "Hello World!";

        
public string HelloWorldString
        {
            
get
            {
                
return helloWorldString;
            }
        }
    }
}

结果,就像我说的那样,Exception发生了。

这是咋回事呢,后来经过调查,发现原来发生了二进制不兼容的问题。所谓二进制不兼容,就是指从代码上,两段代码是OK的,将公共字段换成属性,只要还是这个名字就应该能够正确执行。但是在.NET编译器执行编译之后,编译出来的MSIL代码是不兼容的
你们可以想象,当时写第二段代码也就是引用被我们修改的类的那个类(拗口啊~~~)的时候,当然是在项目中添加了TestDll这个类的引用,否则编译是通不过的。他会有一个编译结果,比如TestHelloWorld.exe。这个exe中会有访问TestDll这个类的MSIL代码,MSIL代码指名道姓:“我要访问名为HelloWroldString的字段”。啊哈~~问题就在这里了,C#代码中访问字段和访问属性的代码是完全一致(兼容)的,但似乎在MSIL中这两种代码是不同(不兼容)的。所以,当我们要求客户把已经没有字段只有属性的DLL版本安装到系统中运行时,发生了这个MissingFieldException。那这样的话,解决起来就很简单了,将最新的代码或者DLL引用到项目中,重新编译一下,问题解决一行代码都不用改,哈哈哈哈~~。等等,啥?TestHelloWorld.exe的代码遗失了?偶~~我的神啊。

特别说明:如果你所有相关的项目都在一个解决方案里进行管理,并且总是同时编译的话是不会出现这个问题的,往往都是在维护项目中偶尔人品不好的状况下发生。

 

以上故事纯属虚构,如有雷同纯属巧合^_^(这行字要小一点)

posted on 2008-08-18 18:38  老兔  阅读(1281)  评论(11)    收藏  举报