您的位置:首页 > 编程语言

.NET编程初学者容易犯的错误和容易混淆的概念

2004-07-22 18:48 253 查看
今天转载了好几篇文章,这篇对偶现在的情况最有用,希望能够对您也有用!?呵!贴在这里!转载自M$中文技术站
一、分不清楚的对象与类

即使是初学者也知道面向对象这个名词。但是很多人搞不清楚“对象”和“类”这两个概念的区别。我不想去解释对象与类的名词概念,这些东西大家翻翻书本就可以找到。

如果你仔细翻阅一下很多IT书籍,会发现,对象(object)与类(class)相互混用。比如,任何一本入门的面向对象书都会告诉你:对象是类的实例。汽车是一个类,而你家的那一辆桑塔纳就是汽车类的一个实例,所以桑塔纳是对象,而汽车就是类。可是,你也会经常发现诸如汽车对象这样的说法,似乎对象又变成了类???

分清楚这个概念,需要知道一点,对象有两个含义:狭义对象和广义对象。看起来有点复杂?但我保证这不是爱因斯坦的相对论。狭义对象是指面向对象编程(OOP)中的对象,狭义对象定义就是:对象是类的实例。广义对象是指面向对象理论和面向对象设计(OOD)中的对象概念,广义对象同时包含类和类的实例两种含义,也就是类也可以称之为广义对象,而类的实例也可以称之为广义对象。

因而,如果一个人或者一本书没有特定针对编程实现,而是泛泛而谈时,对象都是指广义对象,当特指某段程序代码时,对象是指狭义对象。呵呵,没有办法,这就是历史遗留下来所造成的问题。

二、乱用对象继承

我见过一个用ASP.NET的人,他正在编写一个c#代码文件(不是ASP.NET页面),其中写了一个类,他希望在这个类中引用Application中的一个变量,如果是你,你会怎样做?

他是这样做的,比如这个类叫Test,代码如下:

public class Test : System.Web.UI.Page
{
public Test()
{
}

public void MyMethod()
{
object l_value;

l_value = Application["MyVar"];
...
}
}

大家觉得如何?我不知道有多少人会想出这个方法来解决问题。但是他终于跑来找我帮忙,他说这个类一运行就报错了。

说到底,他之所以会将Test类从System.Web.UI.Page继承下来,因为他终于可以在代码中使用Application了。但是这个Application却无法正常工作。Test类并不是一个ASP.NET页面,先不说技术上的问题,仅就面向对象来说就是一个错误的用法,没有承继关系的事物之间是绝对不可以使用继承关系的。如果Human(人类)类从Dog(狗)类继承下来,恐怕没有人赞同吧?因为狗与人之间没有直接的生物关联。

最后提一下上面那个Application不能使用的原因。所有从System.Web.UI.Page继承下来的类都是ASP.NET页面,而每一个ASP.NET页面必须在ASP.NET的进程中进行上下文初始化,也就是该页面必须由ASP.NET的内部进行初始化和创建,直接用new来手动创建,虽然可以在代码使用Application,但是这个Application没有被赋值,所以是null。

三、误解对象方法的作用域

错误的使用对象继承,这样的人确实不少,而不能正确区分对象方法作用域的人多如满天星斗。甚至在一些有多年编程经验的人里
也会犯这种错误。

在一个系统中,看到了别人编写的如下代码:

//产品的数据库操作类
public class ProductionDB
{
public ProductionDB()
{
}

//保存一个产品到数据库中,a_object是一个产品对象实例
public bool SaveProduction(ProductionObject a_object)
{
...
}
//从数据库中删除一个产品,a_object是一个产品对象实例
public bool DeleteProduction(ProductionObject a_object)
{
...
}
//新建一个产品,并返回创建的新产品对象实例
public ProductionObject NewProduction()
{
...
}
//返回指定ID的产品对象
public ProductionObject GetProduction(string a_productionID)
{
...
}
//搜索产品,并返回搜索结果
public ProductionObject[] SearchProduction(object[] a_conditions)
{
...
}
}

我不知道正在看贴的你有没有设计过类似上面这样的代码,也不知道你看到上面代码时是什么心情,反正我看到上面这段代码时差点背过去了,至于是气的背过去还是笑的背过去,我已经分不清楚了。

你会怎样使用这个ProductionDB类来操作产品数据库表?举一个例子:
ProductionObject l_prod;
...
//假设l_prod已经赋值了
ProductionDB l_prodDB = new ProductionDB();
if(l_prodDB.SaveProduction(l_prod)==false) ...
else ...
...

上面是一个典型的使用范例,你看到了,如果要保存一个产品,就必须首先创建一个ProductionDB的实例即new ProductionDB()。问题就在这里了,ProductionDB类中的SaveProduction方法的所有信息全部来自方法参数a_object,也就是方法外部的l_prod变量,而ProductionDB类中除了这5个方法以外,再没有任何其他信息,所以new ProductionDB()有什么意义???为什么要创建一个ProductionDB的实例???

编写者的误解在于,没有区分清楚实例方法与类方法两种方法作用域的区别。凡是像上面这样,方法代码不依赖类的任何信息就应该将方法声明为类方法,而方法依赖和使用类中的成员、信息等,则需要将方法声明为实例方法。

正确的方法编写如下:
public class ProductionDB
{

//保存一个产品到数据库中,a_object是一个产品对象实例
public static bool SaveProduction(ProductionObject a_object)
{
...
}
//从数据库中删除一个产品,a_object是一个产品对象实例
public static bool DeleteProduction(ProductionObject a_object)
{
...
}
//新建一个产品,并返回创建的新产品对象实例
public static ProductionObject NewProduction()
{
...
}
//返回指定ID的产品对象
public static ProductionObject GetProduction(string a_productionID)
{
...
}
//搜索产品,并返回搜索结果
public static ProductionObject[] SearchProduction(object[] a_conditions)
{
...
}
}

将方法声明为static就是类方法,使用方法如下:
ProductionObject l_prod;
...
//假设l_prod已经赋值了
if(ProductionDB.SaveProduction(l_prod)==false) ...
else ...
...

四、滥用数据库连接

滥用数据库连接的人比天上星星还要多的多!!!

我的上面那位程序员也犯下了这个错误,还是那个ProductionDB类,以SaveProduction方法来举例:

public bool SaveProduction(ProductionObject a_object)
{
Connection l_conn;
string l_connString;

l_connString = Application["ConnectionString"];
l_conn = new Connection(l_connString);
...
try
{
try
{
l_conn.Open();
...
}
catch(Exception Eo) {...; return false; }
}
finally
{
l_conn.Close();
}
return true;
}

上面的代码可以正常工作,而且工作的还不错。

但是在某些情况下,机器、软件、数据库、SQL语句等等所有一切都非常的正常,上面代码却会返回false???为什么?因为那个程序员滥用了数据库连接。

每当调用一次SaveProduction方法,系统就会创建一个数据库连接,在方法执行完毕时关闭这个连接,如果是几个人同时测试这段代码,那么几乎不会发生任何问题。

但是如果同时有100个客户调用了SaveProduction方法,会发生什么结果?系统中将在那一霎那间创建100个数据库连接!!!不要说Access这样级别的数据库,就是SQLServer2000也会承受不了。

所以解决方法是不要在一个方法临时创建和关闭数据库连接,不但会造成死机、异常退出等问题,而且也会导致系统性能下降。
正确的方法应该是单独编写一个类或者方法,将所有创建数据库连接的工作放在其中,由这个类来控制数据库连接的数量。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: