posts - 257, comments - 1336, trackbacks - 63, articles - 8
  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理

2004年7月28日

       在给函数参数传递方式作总结的过程中,让我对引用类型有了更进一步的认识。引用类型(reference)是在C++特有的一种新类型(与C相比较),在很多情况下,它提供了与指针操作同等的能力。而且在很多情况下,使用引用是更好的方式。
       
        既然我们在这里要比较指针与应用,那么首先得清楚引用的具体含义。引用是一个const的指针,即一旦引用被赋值了,就不允许改变了,这和声明其他类型的const变量是一样的,同时在声明的同时必须为其赋值,否则是无法编译通过的。(Since you can't change the reference after you define it, you must bind the reference to an object at the beginning of its lifetime.)[1]
    
       第一点,使用引用类型,代码在编译的过程中,编译器会自动地为其解引用(disrefence), 而不需要象使用指针那样,显式的使用解引用操作符(*)。这样就使得代码更加清晰而易读了。这一点在使用enum类型的时候特别明显。下面是一个例子:[2] 

enum day
{
  Sunday, Monday, Tuesday,
  Wednesday, Thursday, Friday,
  Saturday, not_a_day
 }
;
day d;
= Sunday;
while (d <= Saturday)
{
 
// do something with d
 ++d; 
}


        以上代码是不能编译通过的,因为++运算符并不能作用于day类型,虽然我们可以在声明d的时候,使用int而使得编译通过,但是这样做减弱编译器对于类 型的检查能力。那么我们需要做的是将++运算符重载。

day &operator++(day &d)
{
  d 
= (day)(d + 1);
  
return d;
}

         通过返回引用的方式,而不是指针的方式,可以在使用这个被重载的运算符的时候就象使用内建的运算符一样。但是如果使用的是返回指 针的方式的话:     

day *operator++(day *d)
{
  
*= (day)(*+ 1);
  
return d;
}

        在调用这个运算符的时候,就不得不使用++&d了。

        第二点,swap(a,b)这种函数调用的方式,传递的既可以是值,也可以是引用,而这是由函数的型参决定的。因此也有人认为,使用swap(& a, &b)会认为更加清晰,毕竟这样就知道传递的是指针了,一目了然。在这里,
我不由想起C#中的语法,不仅在函数的型参中显式声明传递的是引用还是值,还要在函数被调用的时候体现出来,如swap( ref a, ref b)。从这里可以看出C#在语法上会更加严谨。

        Reference:[1] References and const;
                        [2] An Introduction to References;

posted @ 2004-07-28 19:14 FantasySoft 阅读(2813) | 评论 (3)编辑

       既然都贴了第一篇出来丢脸了,就不介意将第二篇再贴出来了。毕竟这是自己在做实际开发遇到的一些问题,不过,这已经是一年前的问题了,呵呵~~

 
       首先,要感谢CSDN的编辑们,因为是你们让我第一次发表的文章的标题在CSDN的主页上呆了好几天,也让我感激涕零了好几天;接着,要感谢浏览过我的文章的三千多的朋友,不管您对我的文章报以怎样的态度,或者赞许认可,或者嗤之以鼻,毕竟您花费了不少的时间;最后,要谢谢那些给我的文章提出了不少意见的朋友。谢谢你们的鸡蛋。

        ASP.NET与ASP相比,最大的改进莫过于使用了服务器控件。微软发明了.NET,为了模糊基于Web开发和基于Windows 开发的界线,将控件的使用从Windows Form中移植到Web开发中,可谓用心良苦了。今天,就来说一下在我设计第二个网站的时候遇到的一个与控件相关的典型问题。

        在ASP.NET中,我们可以动态的添加控件,可以添加控件相应的事件,这给开发者带来了极大的便利。举个例子来说明吧,部门经理希望录入本部门所有员工的基本情况,或存于数据库,或存于XML文件,以便于管理。作为网站的设计者,并不清楚部门员工的人数,而且,为了网站能够适用于其他部门,录入的页面是不能够固定TextBox的个数。在这种情况下,我就使用了动态添加控件的办法。在录入的页面中有一个Add a new record 的按钮,点击会触发以下的OnClick对应的事件。

public void Create_Record(Object sender, EventArgs e)
{
     TableRow r
=new TableRow();// 创建Table中的一行,即<TR>
     for (int j=0;j<=3;j++)
    
{      
            TableCell c
=new TableCell(); //创建Table中的一列,即<TD>
            c.Width=120;
            
switch (j){
                                 
case 0:
                                         TextBox mytextbox
=new TextBox();
                                         mytextbox.Width
=80;
                                         mytextbox.ID
="InsertPlatform";
                                         c.Controls.Add(mytextbox);                               
                                         
break;
                                 
case 1:
                                         TextBox mytextbox1
=new TextBox();
                                         mytextbox1.Width
=80;
                                         mytextbox1.ID
="InsertRCDPart";
                                         c.Controls.Add(mytextbox1);
                                         
break;
                                 
case 2:
                                         TextBox mytextbox2
=new TextBox();
                                         mytextbox2.Width
=80;
                                         mytextbox2.ID
="InsertKitPart";
                                         c.Controls.Add(mytextbox2);
                                         
break;
                                 
case 3:
                                         LinkButton mylinkbutton
=new LinkButton();
                                         mylinkbutton.Click
+=new EventHandler(Insert_Click);//***
                                         mylinkbutton.ID="Insert";
                                         mylinkbutton.Text
="Insert";
                                         c.Controls.Add(mylinkbutton);
                                         
break;
                                        
                                }

                       r.Cells.Add(c);  
//往行中添加列
                   }

           Table1.Rows.Add(r); 
//往Table中添加行
              
     }


public void Insert_Click(Object sender, EventArgs e)
{        
     //To do something

}


        这样是不是很简单呢?但是,简单归简单,麻烦也跟着来了。动态添加的服务器控件正是问题的根源所在。大家是否注意到以上代码中带星号的那一行呢?这一行的意思当你点击这个动态添加的LinkButton,会触发Insert_Click事件。好了,问题出现了。当我点击了Add a new record按钮之后,Table确实出现了一行,这一行中包含了三个TextBox和一个LinkButton,但是,当我点击这个动态生成的LinkButton,并不能触发相应的Insert_Click事件。我百思不得其解,作为菜鸟的我马上想到了CSDN,在CSDN论坛中发贴时,我用了另外一段代码来说明问题。

<html>
   
<head>
   
</head>
<script language="C#" runat="server">
public 
void Page_Load(Object sender, EventArgs e)
{
     LinkButton mylinkbutton
=new LinkButton();
     mylinkbutton.Text
="say hello";
     mylinkbutton.ID
="hello";
     mylinkbutton.Click
+=new EventHandler(Say_Hello);
     thisform.Controls.Add(mylinkbutton);
 }


public 
void Say_Hello(Object sender,EventArgs e)
{
    Response.Write(
"Hello,World!");
  }


public 
void Say_Goodbye(Object sender,EventArgs e)
  
{
    Response.Write(
"Goodbye,World!");
  }


public 
void AddButton(Object sender,EventArgs e)
{
     thisform.Controls.Add(
new LiteralControl(" "));
     LinkButton mylinkbutton
=new LinkButton();
     mylinkbutton.Text
="say Goodbye";
     mylinkbutton.ID
="goodbye";
     mylinkbutton.Click
+=new EventHandler(Say_Goodbye);
     thisform.Controls.Add(mylinkbutton);

  }


 
</script>
<body>
<form id="thisform" runat="server">
<asp:linkbutton Text="Add Button" OnClick="AddButton" runat="server"/>
</form>
</body>
</html>

       各位可以尝试运行一下,看有什么问题。

       最后,是dragontt让我知道了其中的玄机。原来,Http是一个无状态的协议,每一次同服务器的交互都是作为新的请求来处理。每个页面都是重新生成的,然后根据客户端保存并传递来得ViewState使得服务器端生成的新页面与客户端当前页面的状态相同,接着服务器端会根据客户端的请求,来完成任务。所以,当我点击了Add a new record按钮之后,增加了一个新的LinkButton,但是服务器端新生成的页面并不会记住这个LinkButton,也就不会去执行相应的代码了。

        解决办法是:在AddButton中增加代码:ViewState["test"]=1;     
                               在Page_Load中增加代码:if (ViewState["test"]!=null)   Say_Goodbye ( sender, e ) ;
        通过ViewState的使用,使得服务器端控件的状态得以保持。与这个小程序相对应的,第一个例子的问题也是可以通过这种办法去解决的。

        PS:虽然通过添加两行代码把问题解决了,可是又有新的问题出现了。大家可以尝试一下,当你点击了Add Button之后,出现了另外一个say Goodbye的LinkButton,点击它,正如我们想象一样,"Goodbye World!"出现在屏幕上。但是--如果你不点击动态生成的say Goodbye 的LinkButton,而去点击say Hello的LinkButton,会出现什么呢?        

posted @ 2004-07-28 15:07 FantasySoft 阅读(783) | 评论 (0)编辑

        这是我一年前写下的文章,最近再次看回来的时候,却有很多新的思考。虽然写得很烂,但是抱着敝帚自珍的想法,决定还是贴一下,以搏君一笑了。


        第一次在CSDN发文章,感觉真的是诚惶诚恐。毕竟像我这样一个菜鸟级人物在众高手面前讲述自己的经验无异于班门弄斧,关公面前耍大刀。不过,这一系列文章记述的是我自己的一些经历,是自己在对ASP.NET了解甚少的情况下,接下了建设两个网站任务的经历。或许我把文章定成历险有点夸张,不过在学习与提高的过程中那种山穷水尽疑无路,柳暗花明又一村的感觉着实让人大叫过瘾。就请各位随我走一趟,希望不会让大家失望,同时希望各位高手多多批评,多多责骂。:)

        先说我架设的第一个网站吧。在准备架设第一个网站之前,我有一点ASP的设计实践经验,对于开发环境的选择,我曾经犹豫过,最终我还是选择了ASP.NET。因为我对C#的语言特性很感兴趣,同时对那种意大利面式的ASP实在是无法忍受了。就这样,捧着一本厚厚的书,我就开始投入到ASP.NET之旅了。

        俗话说,万事开头难。可是,学习ASP.NET却是那样的轻易就可以上手了。至于如何上手,如何入门,已经有很多文章讲述了,这里我就不多说了。建设网站的进度很快,以至于我向老板吹嘘我能提前完成任务。老板惊讶于我的的效率,我笑着对他说,这都是ASP.NET的好处啊。然而事情永远都不会如自己所愿的那样,就在整个网站的最后一环——自动发E-Mail上出了问题(终于都到正题了,大家都烦了吧)。

        我原来的打算是利用Namespace中的“System.Web.Mail"中封装的类库去建立MailMessage对象,然后利用Send方法去发送邮件(这个例子到处都有)。当我写完(抄完)了一段程序之后,满心欢喜的以为自己大功告成了,可是我错了。因为我所在的公司的规模很大,公司内部使用Exchange Server进行收发Mail,如果是脱离了Outlook,使用服务器上的SmtpServer会有很长的延迟,甚至会丢信,这样是不允许的。看来现成的东西是不能用的了,稍加思索之后,我觉得应该用客户端调用Outlook发E-Mail的办法。可是,该怎么调用呢?我马上想到了CSDN,就在这里发了帖子。热心的朋友给我想了不少的办法,譬如说利用<a href="mailto">等,可是这些想法都不是我想要的。因为E-Mail的内容是根据用户的选择自动生成的,而邮件列表是与一个DropdownList控件进行绑定的。我一直不停的在尝试,在寻找,甚至跑到www.ASP.NET的论坛上去提问。这个问题就想一条鸿沟,怎么都无法逾越,我几乎都绝望了。就在我觉得这是一个Mission Impossible的时候,是CSDN的saucer给了我最大的帮助,最终的解决方案如下:

建立一个专门发邮件的Sendmail.aspx:

<html>
  
<head>
    
<style type="text/css">
      <!--
        @import ..cssstyle.css;
       -->
      
</style> 
   
</head>
<script language=vbscript >
sub MailSend(ito,isubject,ibody,icc) 
   Dim myOlApp
   Set myOlApp 
= CreateObject("Outlook.Application")
   Dim objMail
   set objMail
=myOlApp.CreateItem(olMailItem)
   objMail.To 
= ito
   objMail.Cc 
= icc
   objMail.Subject 
= isubject
   objMail.HtmlBody 
= ibody
  objMail.Save
  objMail.Send
  Set myOlApp 
= Nothing
end sub
</script>
 
<% 
   
Dim tsubject,tbody,tto,tcc
   tsubject
=Request.QueryString("Subject")
   tbody
=Request.QueryString("Body")
   tto
=Request.QueryString("To")
   tcc
=Request.QueryString("Cc")
   tcc
=Chr(34)+tcc+Chr(34)
   tto
=Chr(34)+tto+Chr(34)
   tsubject
=Chr(34)+tsubject+Chr(34)
   tbody
=Chr(34)+tbody+Chr(34)
   Response.Write(
"<script language=vbscript>MailSend"+tto+","+tsubject+","+tbody+","+tcc)
   Response.Write(
"</"+"script>")  
  
%>

<body leftmargin=20>
 
<table width="90%">
  
<tr valign=middle>
    
<td height=300 align=center>
      
<p Style="font-size:20pt;font-familiy:Verdana, Arial, Helvetica;font-weight:bold;color:#003399">
            Your Mail is sent successfully!
      
</p>
    
</td>
  
</tr>
 
</table>
</body>
</html>

而在另外的需要发Mail的aspx文件中先定义好邮件的标题,正文等属性,然后使用如下语句:

string sendStr="SendMail.aspx?Subject="+System.Web.HttpUtility.UrlEncode(subjectStr)+"&Body="+System.Web.HttpUtility.UrlEncode(bodyStr)+"&To="+System.Web.HttpUtility.UrlEncode(Receiver.Items[0].Value)+"&Cc="+System.Web.HttpUtility.UrlEncode(otherReceiver);
    //Receiver为ListBox控件的ID。

Response.Redirect(sendStr);


是不是觉得很简单呢?踏破铁鞋无觅处,得来全不费功夫啊。这个痛并快乐着的经历给予我更多的思考:调用客户端的对象,这是属于ClientScript的事情,ASP.NET是无法替代ClientScript来做的,就好像你可以轻易的通过Response.Redirect跳转到其他页面,可是却无法找到一个方法来实现打开一个新的Explorer 窗口,将需要打开的页面load进去。只能乖乖的使用将ClientScript写到页面上去实现了:

Response.Write("<script language=javascript>window.open("+ "'http://www.csdn.net');");

Response.Write(
"</" + "script>");


        那个时候通过这个办法解决了调用客户端对象,其实是存在很多的问题的。首先,这里实质是使用了ASP的CreateObject的方法创建Outlook对象实例去完成发送mail的,虽然是可以实现用户的需求,但是总觉得那么不自然,不过那个时候一直都没有找到在ASP.NET中实现类似功能的方法,就只好这样借尸还魂了;第二,没有异常处理,如果发送不成功,根本就没有处理,虽然会弹出一个对话框以提示出现了错误,可是这样是十分不友好的;第三,使用了QueryString去传递邮件内容,一方面有长度限制,一方面不安全,这个失误,我现在觉得是最不可原谅的。 

posted @ 2004-07-28 13:56 FantasySoft 阅读(1125) | 评论 (2)编辑