cnblogs.com

四川汶川发生了大地震,我们为受灾人们祈祷平安。


四川汶川发生了大地震,我们为受灾人们祈祷平安。
地震来时,你躲在哪里? 请把这封信转寄给你所关心的人   !  






教育的失败 …
国家都乱教学生 …
附上我们中华民国搜救总队在 921 搜救时的照片作图解说明
正好可以相呼应 , 更具震撼力及 说服力
血淋淋的历史的 教训印证了文章的 内容
请将文章再转寄出去 ~

地震来时,你躲在哪里?老师教的是错的 !!


也许你已读过,再提醒你一次:地震来时,你 躲在哪里?如果你依照小时候老师教我
们的方法乖乖躲在桌子底下,床铺底下,那么,我必须告诉你,你的伤亡率,高达百
分之九十八!!那该怎么办?美国国际搜救队长教你正确的躲避位置。正确的地震保
命法 -- 转载道格卡普是美国国际搜救队长,自一九八五年至今,他及他的队员己参与
全世界七十九次重大灾难的救灾工作,他曾经爬进近七百栋因为地震、爆炸而严重倒
塌的建筑物 内搜查受困的生还者以及罹难者的遗体。除了参与两年前日本神户大地震
及美国俄克拉荷马市联邦大楼爆炸案救授工作,十二年来国际新闻中的重大灾难救
灾,他都没缺席。

本月十九日他离华前,除了中华民国搜救总队邀他演讲,美国在台协会、加拿大驻华
经贸办事处也邀请他,为美、加外交官员传授在建筑物倒塌时如何求生。国人从小到
大,在防震演习中,老师总是叫学生 躲在课桌下,道格得知这点后,很焦急地一再呼
吁:
不要躲在桌子、床铺下,而是要以比桌B床高度为低的姿势,躲在桌子床铺的旁
边。  



他以先前和土耳其政府、大学合作拍制的地震逃生 录像带,说明不要躲在桌下避震的
道理。透过土耳其政府协助,制作单位爆破一栋废弃大楼,模拟地震时建筑物倒塌的
情形,工作人员先依据「常识」,在桌子床铺等家具旁,同样放置十具模特儿,炸药
引爆后大楼变成断坦残壁,他和搜救队员依予找到二十具模特儿,在桌床下的十具模
特儿,有八具被压成全毁,其中一具甚至头、身、 脚断成三截;他放置的十具模特
儿,则全部安好无事,他解释,建筑物天花板因强震倒塌时,会将桌床等家具压毁,
人如果 躲在其中,后果不堪设想,如果人以低姿势躲在家具旁,家具可以受倒塌物品
的力道,让一旁的人取得生存空间。道格 说,即使开车时遇到地震,也要赶快离开车
子,很多地震时在停车场丧命的人,都   是在车 内被活活压死,在两车之间的人,却
毫发未伤 ( 此段话引图片 说明 ) :强烈地震发生时,如果你正在停车场,千万不要留在
车 内,以免 垮下来的天花板压扁汽车,造成伤害;应该以卧姿躲在车旁,掉落的天花
压在车上,不致直接撞击人身,可能形成一块『生存空间』,增加存活机会 … 。他很慎
重地对在场的一百多位我国搜救队员 说,搜救队员必要在地震中先能自己求得生存,
只有活下来,才能拯救他人性命。他 说,希望大家告诉大家,只要传播这么一点求生
讯息,地震发生时,建筑物 内的伤亡率,可以由百分之九十,遽降为百分之二。请大
家传 阅,增加大家在灾难发生时的生存机率,减少伤害你关心你的朋友吗?如果答案
是肯定的。

请把这封信转寄给你所关心的人
...

 

天使毛毛. 2008-05-16 09:20 发表评论
服务器迁移预告
    为了为大家提供更好的服务,为博客园的进一步发展做准备,我们计划于本周末将博客园迁移至新的服务器、新的机房,迁移将于今晚(5月16日) 20:00开始。
    迁移期间仍然可以访问博客园,但只能浏览内容,不能写博客、发评论、上传文件。
    在迁移期间,大家可以在博客园社区(http://space.cnblogs.com/)进行交流。
    届时,我们将通过服务器迁移临时交流小组向大家汇报迁移进展情况。
    请大家谅解服务器迁移将给您带来的麻烦!
博客园开发团队


dudu 2008-05-16 08:07 发表评论
《博客园精华集》系列:5.15会议记录兼计划
     摘要: 《博客园精华集》系列:5.15会议记录兼计划 包括以下内容,欢迎所有博客园朋友和编委会成员共同讨论。
一、筛选随笔文章流程
二、系统制定
三、联系出版社
四、出书计划  阅读全文

李永京 2008-05-16 00:16 发表评论
希尔排序(shellsort)算法实现
     摘要: 希尔排序(shellsort)又叫增量递减(diminishing increment)排序,是由D.L. Shell发明的,这个算法是通过一个逐渐减小的增量使一个数组逐渐趋近于有序从而达到排序的目的。  阅读全文

银河使者 2008-05-15 22:00 发表评论
Visual Studio “10” Next year Release?

微软今天放出了一份Visual Studio 2008概要介绍演示文稿,不过在最后我们发现了一个有趣的地方,那就是微软打算在2009年推出全新版本,暂时称为Visual Studio “10”.
Visual Studio 2008于去年11月底推出RTM正式版,今年一月底开始零售,想必很多程序员至今还没有摸熟,不过新版本很快就要来了.


不过在Visual Studio “10”之前,微软还会在今年进行一次小规模升级,代号“Rosario”(罗萨里奥,阿根廷东部海港城市)的新版Visual Studio Team System,据称会在业务相关性、质量关注、协作改进等关键领域让软件开发团队获得重大突破.有需要的用户可以下载2008年4月份CTP预览版.

至于Visual Studio “10”会有何新特性,目前还是一无所知,可能会包含“Oslo”(奥斯陆,挪威首都)技术.按照惯例,它应该会命名为Visual Studio 2009.一年大规模升级一次?的确有些太快了

.







PI Wang 2008-05-15 18:51 发表评论
Unity 简单示例代码和向导/Unity Aplication Block
 

Unity 简单示例代码和向导

关于Unity 的说明和下载地址,请访问[微软控制反转和依赖注入容器Unity 1.0发布] http://forum.entlib.com/Default.aspx?g=posts&t=25

下面的范例主要实现:首先,定义ILogger 接口。然后,定义一个实现该接口的具体类 ConsoleLogger。其次,定义一个业务类 CustomerTasks,通过constructor 函数注入ILogger 依赖类,并在CustomerTasks 的其中一个方法内调用 ILogger Log方法。

1. 定义ILogger 接口。

namespace UnitySamples

{

    public interface ILogger

    {

        void Log(string message);

    }

}

2. 定义ConsoleLogger类,实现ILogger 接口。

namespace UnitySamples

{

    public class ConsoleLogger : ILogger

    {

        public ConsoleLogger()

        {

            Console.WriteLine("Hello from constructor");

        }

        public void Log(string message)

        {

            Console.WriteLine(message);

        }

    }

}

3. 定义业务类CustomerTasks

namespace UnitySamples

{

    //create a class that takes an ILogger through constructor injection.

    public class CustomerTasks

    {

        private readonly ILogger logger;

        public CustomerTasks(ILogger logger)

        {

            this.logger = logger;

        }

        public void SaveCustomer()

        {

            logger.Log("Saved customer");

        }

    }

}

创建CustomerTasks类,该类通过constructor 函数注入ILogger依赖类。

4. 使用UnityContainer 依赖注入容器。

using Microsoft.Practices.Unity;

namespace UnitySamples

{

    public partial class Form1 : Form

    {

        public Form1()

        {

            InitializeComponent();

        }

        private void button1_Click(object sender, EventArgs e)

        {

            UnityContainer container = new UnityContainer();

            container.RegisterType<ILogger, ConsoleLogger>(new ContainerControlledLifetimeManager());

            CustomerTasks tasks1 = container.Resolve<CustomerTasks>();

            CustomerTasks tasks2 = container.Resolve<CustomerTasks>();

            tasks1.SaveCustomer();

            tasks2.SaveCustomer();   

        }

    }

}

通过RegisterType 方法注册ILogger Singleton 实例。然后调用UnityContainerResolve方法,并指定类型实例为 CustomerTasks。由于前面并没有注册该类,UnityContainer 将负责生成一个CustomerTasks 的实例并返回。因为CustomerTasks 类中声明了custructor函数注入ILogger 接口,UnityContainer 将使用先前注册的ILogger 类型,自动实例化ConsoleLogger对象。



EntLib 2008-05-15 18:37 发表评论
在Firefox中通过AJAX跨域访问Web资源
     摘要: 本文讨论了如何解决ajax跨域访问的问题,以及阐述了XMLHttpRequest中某些属性和方法在不同浏览器中的区别。  阅读全文

银河使者 2008-05-15 16:56 发表评论
C#和Java的闭包-Jon谈《The Beauty of Closures》

原文:http://csharpindepth.com/Articles/Chapter5/Closures.aspx

第一段略。。。

大多数讲闭包的文章都是说函数式语言,因为它们往往对闭包的支持最完善。当你在使用函数式语言时,很可能已经清楚了解了什么是闭包,所以我想写一篇在经典OO语言出现的闭包有什么用处应该也是很合适的事情。这篇文章我准备讲一下C#(1、2、3)和JAVA(7以前版本)的闭包。

什么是闭包?

简单来讲,闭包允许你将一些行为封装,将它像一个对象一样传来递去,而且它依然能够访问到原来第一次声明时的上下文。这样可以使控制结构、逻辑操作等从调用细节中分离出来。访问原来上下文的能力是闭包区别一般对象的重要特征,尽管在实现上只是多了一些编译器技巧。

利用例子来观察闭包的好处(和实现)会比较容易, 下面大部份内容我会使用一个单一的例子来进行讲解。例子会有JAVA和C#(不同版本)来说明不同的实现。所有的代码可以点这里下载

需求场景:过滤列表

按一定条件过滤某个列表是很常见的需求。虽然写几行代码遍历一下列表,把满足条件的元素挑出来放到新列表的“内联”方式很容易满足需求,但把判断逻辑提取出来还是比较优雅的做法。唯一的难点就是如何封装“判定一个元素是否符合条件”逻辑,闭包正好可以解决这个问题。

虽然我上面说了“过滤”这个词,但它可能会有两个截然不同的意思“把元素滤出来放到列表里”或者把“把元素滤出来扔掉”。比如说“偶数过滤”是把“偶数”保留下来还是过滤掉?所以我们使用另一个术语“断言”。断言就是简单地指某样东西是不是满足某种条件。在我们的例子中即是生成一个包含了原列表满足断言条件的新列表。

在C#中,比较自然地表现一个断言就是通过delegate,事实上C# 2.0有一个Predicate<T>类型。(顺带一提,因为某些原因,LINQ更偏向于Func<T, bool>;我不知道这是为什么,相关的解释也很少。然而这两个泛型类的作用其实是一样的。)在Java中没有delegate,因此我们会使用只有一个方法的interface。当然C#中我们也可以使用interface,但会使得代码看起来很混乱,而且不能使用匿名函数和拉姆达表达式-C#中符合闭包特征的实现。下面的interface/delegate供大家参考:

// Declaration for System.Predicate<T>
public delegate bool Predicate<T>(T obj)
// Predicate.java
public interface Predicate<T>
{
    boolean match(T item);
}

在两种语言中过滤用的代码都比较简单,得先说明在这里我会避免使用C#的Extension Method来让代码看起来更加简单明了。-但是使用过LINQ的人要注意where这个Extension Method。(它们的延迟执行有些区别,但这里我会避免触及)

// In ListUtil.cs
static class ListUtil
{
    public static IList<T> Filter<T>(IList<T> source, Predicate<T> predicate)
    {
        List<T> ret = new List<T>();
        foreach (T item in source)
        {
            if (predicate(item))
            {
                ret.Add(item);
            }
        }
        return ret;
    }
}
// In ListUtil.java
public class ListUtil
{
    public static <T> List<T> filter(List<T> source, Predicate<T> predicate)
    {
        ArrayList<T> ret = new ArrayList<T>();
        for (T item : source)
        {
            if (predicate.match(item))
            {
                ret.add(item);
            }
        }
        return ret;
    }
}

(两种语言中我都写了一个Dump方法用来输出指定list的内容)

现在我们已经定义好“过滤”的方法,接下来就是要调用它。为了演示闭包的重要作用,我会先使用一个简单的不需要使用到闭包都能解决的案例,然后再进一步到比较难的案例。

过滤案例1:找出长度较短的字符串(固定长度)

我们的需求场景都会比较简单基础,但希望大家能从中看出它们的不同之处。我们将会有一个字符串list,然后根据这个list生成另一个只包含长度较“短”的字符串list。建立list很简单-建立断言才是难点。

在C# 1.0中只能通过单独的方法来表现一个断言逻辑,然后再创建一个delegate指向该方法。(当然由于代码使用了泛并不能真地在C# 1.0下面通过编译,但要注意delegate实例是如何被建立的-这是重点)

// In Example1a.cs
static void Main()
{
    Predicate<string> predicate = new Predicate<string>(MatchFourLettersOrFewer);
    IList<string> shortWords = ListUtil.Filter(SampleData.Words, predicate);
    ListUtil.Dump(shortWords);
}

static bool MatchFourLettersOrFewer(string item)
{
    return item.Length <= 4;
}

在C# 2.0中有三种方式实现,第一,使用上面一样的代码;第二,利用方法组转换(Method Group Conversion)对代码进行简化;第三,利用匿名函数将断言直接写在调用上下文中。使用方法组转换比较浪费时间-它只是把new Predicate<string>(MatchFourLettersOrFewer) 变成了 MatchFourLettersOrFewer。在示例代码中有它的实现(在Example1b.cs中)。相对而言,匿名函数要有趣得多:

static void Main()
{
    Predicate<string> predicate = delegate(string item)
        {
            return item.Length <= 4;
        };
    IList<string> shortWords = ListUtil.Filter(SampleData.Words, predicate);
    ListUtil.Dump(shortWords);
}

这样一来,就不再需要一个外部独立的方法用来封装断言逻辑,并且,断言放在了被使用的点上。很好很强大。它背后是怎么工作的呢?如果你用ildasm或者reflector去看一下生成的代码,你会发现其实它了第一个版本产生的代码很大程度是一样的,编译器只是帮我们完成了某些工作。稍后我们会看到它更强悍的能力。

在C# 3.0中除了有上面三种方式,还有拉姆达表达式。对于本文来讲,拉姆达表达式只是匿名函数的一个简化形式。(这两种东东最大的区别在于LINQ中的拉姆达表达式能被转换成表达式树,但这与本文无关)使用拉姆达表达式:

static void Main()
{
    Predicate<string> predicate = item => item.Length <= 4;
    IList<string> shortWords = ListUtil.Filter(SampleData.Words, predicate);
    ListUtil.Dump(shortWords);
}

由于在右边使用了<=,看起来像是有个大箭头指着item.Length,但为了保持前后一致,只好请大家将就着看了。这里其实可以写成等价的Predicate<string> predicate = item => item.Length < 5

在Java中没有delegate-只能实现上面定义的interface。最简单的方法就是定义一个类并实现该interface,如:

// In FourLetterPredicate.java
public class FourLetterPredicate implements Predicate<String>
{
    public boolean match(String item)
    {
        return item.length() <= 4;
    }
}

// In Example1a.java
public static void main(String[] args)
{
    Predicate<String> predicate = new FourLetterPredicate();
    List<String> shortWords = ListUtil.filter(SampleData.WORDS, predicate);
    ListUtil.dump(shortWords);
}

这里没有使用任何华丽的语言特性,为了实现一点小小的逻辑,它使用了一整个独立的类。根据Java的惯例,类应该放在单独的文件里,这使得程序的可读性变差。当然可以使用嵌套类的方式来避免这种问题,但逻辑还是离开了使用它的地方-相当于啰嗦版的C# 1.0解决方案。(这里不打算给出嵌套版的实现代码,有需要的朋友可以看看打包代码里面Example1b.java。)Java可以通过匿名类把代码书写成内联的方式,在匿名类的光芒照射下,代码进化了:

// In Example 1c.java
public static void main(String[] args)
{
    Predicate<String> predicate = new Predicate<String>()
    {
        public boolean match(String item)
        {
            return item.length() <= 4;
        }
    };
    
    List<String> shortWords = ListUtil.filter(SampleData.WORDS, predicate);
    ListUtil.dump(shortWords);
}

如你所见,比起C# 2.0和C# 3.0的代码,这个显得还是比较啰嗦了点,但至少代码被放在了它应该在的地方。这就是Java目前支持的闭包……接下来本文进入第二个例子。

过滤案例2:找出长度较短的字符串(可变长度)

目前为止我们的断言并不需要访问到原来的“上下文”-长度是硬编码的,然后字符串是以参数的形式传进去的。现在,需求变动一下,允许用户指定多长的字符串才算是合适的。

首先,我们回到C# 1.0。它其实不支持真正的闭包-找不到一块简单的地方来存储我们需要的变量。当然,我们可以在当前方法的上下文中声明一个变量来解决这个问题(比如利用静态成员变量),但这明显不是一个好的解决方法-理由只有一个,类马上变成了线程不安全的。解决的方法就是不要把状态存储在当前上下文中,转而存储在新建的类中。这么一来,代码看起来跟原来的Java代码非常相似,区别只是这里使用delegate,而Java使用interface。

// In VariableLengthMatcher.cs
public class VariableLengthMatcher
{
    int maxLength;

    public VariableLengthMatcher(int maxLength)
    {
        this.maxLength = maxLength;
    }

    /// <summary>
    /// Method used as the action of the delegate
    /// </summary>
    public bool Match(string item)
    {
        return item.Length <= maxLength;
    }
}

// In Example2a.cs
static void Main()
{
    Console.Write("Maximum length of string to include? ");
    int maxLength = int.Parse(Console.ReadLine());

    VariableLengthMatcher matcher = new VariableLengthMatcher(maxLength);
    Predicate<string> predicate = matcher.Match;
    IList<string> shortWords = ListUtil.Filter(SampleData.Words, predicate);
    ListUtil.Dump(shortWords);
}

相对来说,C# 2.0和C# 3.0的改动要小得多:只需将硬编码的常量改成变量即可。先不管这背后的原理-一会看完Java版的代码后再来研究这个问题。

// In Example2b.cs (C# 2)
static void Main()
{
    Console.Write("Maximum length of string to include? ");
    int maxLength = int.Parse(Console.ReadLine());

    Predicate<string> predicate = delegate(string item)
    {
        return item.Length <= maxLength;
    };
    IList<string> shortWords = ListUtil.Filter(SampleData.Words, predicate);
    ListUtil.Dump(shortWords);
}
// In Example2c.cs (C# 3)
static void Main()
{
    Console.Write("Maximum length of string to include? ");
    int maxLength = int.Parse(Console.ReadLine());

    Predicate<string> predicate = item => item.Length <= maxLength;
    IList<string> shortWords = ListUtil.Filter(SampleData.Words, predicate);
    ListUtil.Dump(shortWords);
}

Java版的代码(使用了匿名类的那个版本)改动也比较简单,但有一点不爽的是-必须把参数声明为final。了解其原理前先来看一下代码:

// In Example2a.java
public static void main(String[] args) throws IOException
{
    System.out.print("Maximum length of string to include? ");
    BufferedReader console = new BufferedReader(new InputStreamReader(System.in));
    final int maxLength = Integer.parseInt(console.readLine());
    
    Predicate<String> predicate = new Predicate<String>()
    {
        public boolean match(String item)
        {
            return item.length() <= maxLength;
        }
    };
    
    List<String> shortWords = ListUtil.filter(SampleData.WORDS, predicate);
    ListUtil.dump(shortWords);
}

那么,C#和Java的代码到底有什么不同呢?在Java中,变量的被匿名类捕获。在C#中,变量本身被delegate捕获。为了证明C#捕获了变量本身,我们来改一下C# 3.0的代码,使变量的值在变量在过滤后发生改变,看看改变是否反映到下一次过滤:

// In Example2d.cs
static void Main()
{
    Console.Write("Maximum length of string to include? ");
    int maxLength = int.Parse(Console.ReadLine());

    Predicate<string> predicate = item => item.Length <= maxLength;
    IList<string> shortWords = ListUtil.Filter(SampleData.Words, predicate);
    ListUtil.Dump(shortWords);

    Console.WriteLine("Now for words with <= 5 letters:");
    maxLength = 5;
    shortWords = ListUtil.Filter(SampleData.Words, predicate);
    ListUtil.Dump(shortWords);
}

注意,我们只是改变局部变量的值,而并没有重新创建delegate的实例,或者其它等价的操作。由于delegate其实是直接访问这个局部变量,所以其实它是能够知道变量发生的变化。再进一步,接下来在断言逻辑中直接对变量进行修改:

// In Example2e.cs
static void Main()
{
    int maxLength = 0;

    Predicate<string> predicate = item => { maxLength++; return item.Length <= maxLength; };
    IList<string> shortWords = ListUtil.Filter(SampleData.Words, predicate);
    ListUtil.Dump(shortWords);
}

我不打算再深入地讲这些是怎么实现的-《C# in Depth》第5章讲的都是这些细节。只是希望你们一些对“局部变量”的观念认识被完全颠倒。

我们已经看到了C#是如何对捕获的变量进行修改的,那Java呢?答案只有一个:你不能对捕获的变量进行修改。它已经被声明为final,所以这个问题其实是很无厘头的。而且就算你人品值爆糟,突然间能对该变量进行更改,也会发现断言逻辑根本对修改毫无反应。变量的值在断言声明的时候被拷贝并存储到匿名类内。不过,对于引用变量,它的成员发生改变还是能够被知道的。比如说,如果你引用了一个StringBuilder,然后对它进行Append操作,那在匿名类中是可以看到StringBuilder的改变。

对比捕获策略:复杂性VS功能

明显Java的设计局限性比较大,但也同时也比较容易理解,不容易发生概念混淆的情况,局部变量的行为和一般情况下没什么不同,大多数情况下,代码看起来也更简单易懂。比如下面的代码,利用Java runable interface和.NET Action delegate-两个都是会执行一些操作,不需要参数,也不返回任何值。首先看看C#的代码:

// In Example3a.cs
static void Main()
{
    // First build a list of actions
    List<Action> actions = new List<Action>();
    for (int counter = 0; counter < 10; counter++)
    {
        actions.Add(() => Console.WriteLine(counter));
    }

    // Then execute them
    foreach (Action action in actions)
    {
        action();
    }
}

会输出些什么?其实我们只声明了一个counter变量-所以其实所有的Action捕获的都是同一个counter变量。结果就是每一行都输出数字10。为了把代码“修正”到我们预期的效果(如输出0到9),则需要在循环体中使用另一个局部变量:

// In Example3b.cs
static void Main()
{
    // First build a list of actions
    List<Action> actions = new List<Action>();
    for (int counter = 0; counter < 10; counter++)
    {
        int copy = counter;
        actions.Add(() => Console.WriteLine(copy));
    }

    // Then execute them
    foreach (Action action in actions)
    {
        action();
    }
}

这样,每次循环体在执行的时候,都会取得一份counter的拷贝,而不是它本身-所以每个Action取得了不同的变量值。如果看一下编译器生成的代码,你就会完全明白这种结果是合情合理的,但这对于大多数第一次看到代码的程序员来说,其直觉得出的结果往往是相反的。(包括我)

在Java中则完全不存在第一个例子的情形-你根本不可能捕获到counter变量,因为它并没有被声明为final。使用final变量,最终得到下面类似C#的代码:

public static void main(String[] args)
{
    // First build a list of actions
    List<Runnable> actions = new ArrayList<Runnable>();        
    for (int counter=0; counter < 10; counter++)
    {
        final int copy = counter;
        actions.add(new Runnable()
        {
            public void run()
            {
                System.out.println(copy);
            }
        });
    }
    
    // Then execute them
    for (Runnable action : actions)
    {
        action.run();
    }
}
有了“捕获变量的值”语义存在,代码显得清晰明了,更符合直觉。尽管代码看起来比较啰嗦没有C#那么爽,但Java强制只能使用唯一正确的方式去书写代码。但同时当你需要像原来C#代码的那种行为时(有时候确实有这种需求),用Java实现起来是会比较麻烦。(可以用一个只有一个元素的数组,然后引用这个数组,再对数组元素进行操作,代码看起来会比较杂乱)。

我到底想讲些什么?

在例子中,我们可以看到了闭包好处其实不多。当然,我们把控制结构和断言逻辑成功分拆开来,但这并没有使代码比原来的更加简洁。这种事经常发生,新特性在简单的情形往往是看起来没想像中那么好,有那么大的作用。闭包通常带来的好处,是可组合性,如果你觉得这么说有些扯淡,没错-这也是问题的一部份。当你对闭包运用很熟练甚至有些迷恋的时候,两者之间的联系就会变得越来越明显,否则是不容易看出其玄妙所在。

闭包不是被设计来提供可组合性。它做的不过是让delegate实现起来更加简单(或者只有一个方法的interface,下面统一用delegate简称)。如果没有闭包,直接写一个循环结构其实是比把封装了一些相关逻辑的delegate传给另一个方法去执行循环要来得简单。即使可以通过delegate调用“在已有类中添加的方法”,最终你还是没办法把逻辑代码放在最合适的地方,而且没了闭包提供的信息存储便利,则必须依靠方法外部的上下文来存储某些信息。

可见,闭包使delegate更加易用。这就意味着值得将API设计成为使用delegate的形式。(我认为这种情况并不适用于.NET 1.1下面基本上只能用来处理线程和订阅事件的delegate)当你开始用delegate的方式去解决问题时,如何去做变得显而易见。比如,最常见的就是创建一个用AND或者OR(也包括其它逻辑操作符)将两个断言串连起来的Predicate<T>。

当把某个delegate产生的结果装填进另一个列表,或者对delegate进行加工产生新的,就会有完全不同的组合方式,如果将逻辑当作可以被传递的某种数据来考虑时,所有不同类型的选择都是可行的。

这种编码方式的好处远不止上面说的那么多-整个LINQ都是基于这种方式。我们创建的过滤器只是一个可以将有序数据转换成另一组数据的例子。另外还有排序,分组,联接另一组数据和Projecting等操作。使用传统的编码方式去写这些操作虽不是非常痛苦的事情,但是如果“数据管道”中转换操作越来越多时,复杂性随之提高,另外,LINQ赋于对象延迟执行和数据流的能力,这种一次循环执行多次操作方式明显比多次循环执行一次操作要节约很多内存。即使每一个单独的转换操作被设计得很聪明高效,复杂性上还是依旧无法取得平衡-通过闭包封装简明扼要的代码片断以及良好设计的API带来的组合能力可以很好去除复杂性。

结论

刚开始接触闭包,可能不会对它有深刻印象。当然,它使得你的interface或者delegate实现起来更简单(取决于语言)。其威力只有在相关类库利用了它的特性之后才能体现出来,允许你将自定义行为放在合适的地方。当同一个类库同时允许你将几个简单的步骤以比较自然的方式组合起来实现一些重要行为时,其复杂性也只是几个步骤的总和-而不是大于这个总和。我不是赞同某些人鼓吹的可组合性是解决复杂性的银弹,但它肯定是很有用的技巧,而且由于闭包使得它在很多地方可以得以实施。

拉姆达表达式最重要特点就是简洁。看一下之前的Java和C#的代码,Java的代码显然比较笨拙冗长。很多Java闭包的倡议都是想解决这个问题。稍后我会发一篇文章讲一下我对这些不同倡议的看法。



Klesh Wong 2008-05-15 16:41 发表评论
C#发现之旅第一讲 C#-XML开发
     摘要:

为了让大家更深入的了解和使用C#,我们将开始这一系列的C#发现之旅的技术培训。考虑到各位大多是进行WEB数据库开发的,因此培训内容将是C#在WEB数据库开发的以外的应用,在未来的C#发现之旅,我们将一起去探索发现C#的其他未知的领域,从而拓宽我们的视野,增强我们的软件开发能力。
根据大家的基本情况,为了贯彻发现之旅这个主题,目前在C#发现之旅系列教程中规划的内容主要是图形开发和XML开发等非WEB数据库开发技术,并计划编排了多节课程,按照由浅入深,循序渐进的步骤逐步探索发现C#在这些方面的运用,从而更深入的理解和掌握C#软件开发。  阅读全文

袁永福 2008-05-15 15:41 发表评论
致歉

今天下午由于同时边接过多,造成网站访问速度很慢,给大家带来了麻烦,请大家谅解!
我们正在努力解决这个问题!目前情况有所缓解。



dudu 2008-05-15 15:30 发表评论
爱心无价
    这些天我正计划找一份新的工作,正处于待业状态。由于原来公司组织募捐活动的流程的性质,我无法参与原公司的募捐活动了。就在女朋友所在公司的的募捐活动中让她在原计划捐款金额的基础上加了一倍。数目不大,无法向姚明一样一下子500万,但尽自己的微薄之力吧。
 
    在此,提醒各位网友,务必留意短信或电话的诈骗活动。有一些昧良心的人利用大家救灾的机会趁机行骗。大家不要在非规范的募捐箱募捐,救命钱不要装进骗子的腰包。

    通过红十字会的募捐帐号转帐的过程,各大银行为何还要收手续费,这是给灾区人民的救命钱,你们为什么还要从中获利,难道无法为此账号开通一个绿色通道吗?



Johnson2008 2008-05-15 14:32 发表评论
ASP.NET AJAX ToolKit 中Accordion的关于OnItemCommand的bug, 通过修改重编译源文件完成修补
3.0.30229.0版本的Ajax toolkit 的dll.
截止昨晚查看是http://asp.net/ajax/上能下载到的最新版本

因为这边的一个简单想法需求,需要在Accordion中自定义好header和content的templete后用自己的datasource进行绑定

其实用法和repeater差不多 主要问题在于OnItemCommand事件的参数AccordionCommandEventArgs e,理应是这个
不过运行之后系统提示编译错误,对于OnItemCommand无可用overload,而只认CommandEventArgs.

而实际上AccordionCommandEventArgs 是继承于CommandEventArgs,并且前者多实现一个Container属性,这个属性能获得当前Pane里的对象。

还好这个ajax toolkit是完全开源的,下载了最新版本发现这个bug没有更新过,尝试下自己修改再编译,竟然成功。难道之前没人用动态数据绑过Accordion?

项目中的accordion文件夹中的accordion.cs里
第65行我认为理应是如下表示,可是原本却是public event CommandEventHandler ItemCommand;

        /// <summary>
        /// Event to raise when a command is fired
        /// </summary>
        public event EventHandler<AccordionCommandEventArgs> ItemCommand;

有空大家一起来研究,我这的版本是对应.net framework 3.5的,那个对应2.0版本的toolkit没试过

不过话说回来现在虽然能触发pane中的button事件了,不过还是有些其他问题的,不知道是因为accordion本身就还是半完成品呢才留这么个bug的。。。
搜遍google baidu都没看到类似问题 发上来大家讨论讨论。。。





SHUFE.41 2008-05-15 12:52 发表评论
利用div+css在GridView模版列打造可定制的ToolTip风格

    在项目中,我们经常会遇到需要查看数据表中所有字段详细信息的情况,通常我们会把某些必要的字段如ID等显示出来,然后把其它字段汇总放到DetailView或者另一个页面,然后提供一个“查看详细信息”的LinkButton,抑或是利用脚本弹出另一个Web窗口。这些做法都稍显蹩脚,如果只是为“查看详细信息”而查看详细信息(额,有些拗口),我们还有更好的解决办法,利用div+css来达到类似ToolTip的效果。

 

    众所周知,一些HTML元素或者ASP.NET控件都有一个叫做ToolTip的属性。这个属性主要是在鼠标移上的时候显示一些提示和描述信息。不幸的是,它不能像InnerHtml属性一样内嵌HTML代码。比如:

        <asp:Image ID="Image1" ImageUrl="~/images/more.gif" ToolTip="<b>抗震救灾 众志成城</b>" runat="server" />
        <asp:Label ID="Label2" runat="server" Text="<b>抗震救灾 众志成城</b>"></asp:Label>

运行效果如图:

     

    并没有达到我们预期的效果,好了,下面我们利用div+cssGridView模板内达到我们想要的效果。

    首先,我们添加一个数据源控件。

        <asp:SqlDataSource
            ID="SqlDataSource1"
            runat="server"
            ConnectionString="<%$ ConnectionStrings:MySqlConnectionString %>"
            ProviderName="System.Data.SqlClient"
            SelectCommand="SELECT * FROM [authors]">
        </asp:SqlDataSource>

         Web.config配置如下:

    <connectionStrings>

        <add name="MySqlConnectionString" connectionString="Data Source=.\sqlexpress;AttachDBFilename=|DataDirectory|pubs.mdf;Integrated Security=True" />

    </connectionStrings>

  

    再添加一个GridView

 

        <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataKeyNames="au_id"

            DataSourceID="SqlDataSource1" AllowPaging="True">

            <Columns>

                <asp:BoundField DataField="au_id" HeaderText="au_id" ReadOnly="True" SortExpression="au_id" />

                <asp:BoundField DataField="au_lname" HeaderText="au_lname" SortExpression="au_lname" />

                <asp:TemplateField HeaderText="au_fname" SortExpression="au_fname">

                    <ItemTemplate>

                                          <%--想要添加的代码--%>                     

                    </ItemTemplate>

                </asp:TemplateField>

            </Columns>

        </asp:GridView>

 

        Pubs数据库中的authors表有很多字段,我们只在Gridview里面显示前三个,之后,我们重点在au_fname模板列上做文章。

我们要达到这样的效果:每一行的au_fname后面都有一个小图片,鼠标移上时就弹出tooltip,里面有我们想要的详细信息。

首先,我们需要一个总的div容器。

                    <ItemTemplate>

                          <div>  

                          </div>               

                    </ItemTemplate>

    接着绑定要显示的字段:

                    <ItemTemplate>

                           <div>  

                               <asp:Label ID="Label1" runat="server" Text='<%# Bind("au_fname") %>'></asp:Label>

                           </div>               

                    </ItemTemplate>

 

    接着我们再添加一个div,这个div的作用十分重要,不可或缺,它主要是协调和Label1的布局(display:inline)并且框定tooltip的位置(position:relative),使tooltip不至于在页面上“乱跑”。

                    <ItemTemplate>
                        <div>
                            <asp:Label ID="Label1" runat="server" Text='<%# Bind("au_fname") %>'></asp:Label>
                            <div style="display:inline; position:relative;z-index:1000">
                                <img src="images/more.gif" alt="" />
                                <div id="div<%# Eval("au_id") %>" class="tooltip">
                                    <strong>phone</strong>:<%# Eval("phone")%><br />
                                    <strong>address</strong>:<%# Eval("address")%><br />
                                    <strong>city</strong>:<%# Eval("city")%><br />
                                    <strong>state</strong>:<%# Eval("state")%><br />
                                    <strong>zip</strong>:<%# Eval("zip")%><br />
                                    <strong>contract</strong>:<asp:CheckBox ID="CheckBox1"                  Checked='<%#Convert.ToBoolean(Eval("contract").ToString())%>' runat="server" />
                                </div>  
                            </div>                 
                        </div>                        
                    </ItemTemplate>

        Iddiv<%# Eval("au_id") %>div就是我们要的类似tooltip的容器,它是可定制的,也就是说,它可以是相当复杂的,你可以往里面添加任何你想要的HTML代码。

    编辑模板列,使其对齐:


    position

   

   

    下一步,我们要利用CSS代码来控制这个div,使其状态在初始时隐藏,当img对象的onmousemove事件发生时显示,onmouseout事件发生时又隐藏。

    下面是CSS代码和Javascript脚本,都很简单。

    <style type="text/css">

        .tooltip

        {

            display: none;

            position: absolute;

            z-index: 1001;

            left: 10px;

            top: 15px;

            width: 170px;

            font-family: Trebuchet MS, Lucida Sans Unicode, Arial, Sans-Serif;

            font-size: 0.8em;

            padding: 3px;

            border: dotted 1px;

            background-color: InfoBackground

        }

</style>

 

    <script type="text/javascript">

     function showPanel(divName) {

            var ctl = window.document.getElementById(divName);

            ctl.style.display = 'block';

            ctl.scrollIntoView();

     }

     function hidePanel(divName) {

            var ct2 = window.document.getElementById(divName);

            ct2.style.display = 'none';

     }

    </script>

 

好了,终于完成任务了,看一看实际效果吧。


show



这里有一个问题就是:

       bug

   

这样相当难看,请熟悉CSS的朋友给解决一下,谢谢了!



源代码下载:SmartToolTip.zip

 

安眠花 2008-05-15 12:04 发表评论
框架设计团队/小组建设方案
     摘要: 对于 团队宗旨、团队目标、对团队名称的解释、我在团队中的位置、对于团队成员的假设、团队工作、团队活动、团队成员的加入 的说明。  阅读全文

Jimmy Zhang 2008-05-15 11:49 发表评论
5.12地震报道感人语录摘抄"我就一句话,是人民在养你们,你们自己看着办"!


请允许我发到首页,看完网络上的报道,我鼻子酸酸的,眼泪莫名而出,男人哭吧不是罪!








一位战士 :  "求求你们让我再去救一个!我还能再救一个! "

温总理 :  救人心切的温总理罕有地发怒:“当温总理接到电话,听说由于桥梁倒塌,彭州市10万群众被堵在山中,救灾人员和物资无法运入时,总理在电话里大喊,‘我不管你们怎么样,我只要这10万群众脱险,这是命令!’之后他把电话挂了。”

总理向前往汶川的登机部队领导发出指示,“我就一句话,是人民在养你们,你们自己看着办。

记者 :  中国的王牌军再次出动(15军是解放军的甲等主力军,他的战绩就是美国人为之色变的——上甘岭) ,很多人都写了遗书


我们的"平民总理"最近头发白了很多,辛苦了!



天真的好蓝啊 2008-05-15 09:35 发表评论
More Posts Next page »