ILove's Dev Home - 休息的时候不要忘记 别人还在奔跑

  博客园 :: 首页 :: 新随笔 :: 联系 ::  :: 管理 ::
  19 随笔 :: 5 文章 :: 237 评论 :: 5 Trackbacks

我的评论

共2页: 1 2 下一页 
re: 《Understand Asp.Net Further》 - 目录 没有昵称 2008-06-19 21:10  
@xiao_p
3x,生命周期很重要,我漏掉了,多谢帅哥提醒哈~
re: 《Understand Asp.Net Further》 - 目录 没有昵称 2008-06-19 09:54  
@westhot
现在还是在非脱产状态下写东西,速度也快不了。频率大约每周一篇左右吧,看平时的工作量多少了。
re: 《Understand Asp.Net Further》 - 前言 没有昵称 2008-06-19 09:50  
@海东青
呵呵,没错,我也是从不知道到知道的。但刚开始的时候,许多问题都是非常基础的,这些要么在快速入门或者MSDN里面直接就能找到,要么google一下就有一堆答案。

对于这些问题,我认为应该主动的去寻找答案,而不是发个帖子被动的等别人贴答案。一个好的程序员要能够自己找到答案,而不能遇到问题就等着别人来喂答案。在主动寻找答案的过程中会有很多额外的收获。
re: 《Understand Asp.Net Further》 - 目录 没有昵称 2008-06-19 00:45  
@Jeffrey Zhao
哈哈,老赵是高手,这些东西对于你来说可能没多少营养,^_^
re: 《Understand Asp.Net Further》 - 目录 没有昵称 2008-06-18 20:48  
@李永京
谨记,^_^^_^
有必要实时检测么?
焦点离开时或者提交前检测一次应该就可以了吧。提示用户格式不对、哪里不对、为什么不对就可以了。
可以用自定义验证控件 + 正则表达式。
@lcg22it
如果你想让a等于字符串“&”,必须写a = UrlEncode("&")。
到时候url里面就不是?a=&&b=2这样子了。
自己试试
@lcg22it
a的值为空啊。
这个。。。。。

帅哥啊。。。。。整个字符串调用UrlEncode就可以了,没必要一个个参数拆分开来编码再串起来。。。
re: 教你如何制作精美的圆角表格 没有昵称 2008-04-25 01:42  
貌似css中有实现圆角矩形的这个东东
re: 设定 GridView 内框线的颜色 没有昵称 2008-04-25 01:41  
还是通过给单元格设置css样式,在样式表中设置颜色更加灵活一些。
re: C# 浅拷贝和深拷贝 学习笔记 没有昵称 2008-04-25 01:34  
sorry,你的说法是不正确的。“只传递一个引用指针”不是拷贝。

浅拷贝是指:在拷贝时只复制类的所有字段的值;如果字段是值类型,则复制其值;如果字段是引用类型,则复制一个引用指针。

深拷贝是指:在拷贝时复制类的所有字段的值,如果字段是值类型,则复制过来;如果字段是引用类型,则会将这个引用指针指向的对象也克隆一下。

所以,浅拷贝是指只拷贝一层、不递归拷贝;而深拷贝是指递归拷贝。

举例:
MyClass
{
int A;
object B;
MyClass Copy();
}

object obj = new object();
MyClass a = new MyClass();
a.A = 1;
a.B = obj;
MyClass b = a.Copy();

不管是浅拷贝还是深拷贝,a和b指向的都不是同一个对象了。而且因为字段A是值类型,所以a.A和b.A的值相等但不在同一个内存地址上。
如果是浅拷贝,此时a.B与b.B是指向的同一个引用;因为只是复制了a这个指针的值也就是obj的内存地址;
如果是深拷贝,则此时a.B与b.B就不是指向的同一个引用了。b.B应该是指向a.B克隆后的一个新的内存地址。

所以他们的实现就如:
浅拷贝:
MyClass MyClass::Copy
{
MyClass copy = new MyClass();
copy.A = this.A;
copy.B = this.B;
return copy;
}
深拷贝:
MyClass MyClass::Copy
{
MyClass copy = new MyClass();
copy.A = this.A;
copy.B = this.B.Copy(); // 假设 this.B 有一个 Copy 方法来实现深拷贝。
return copy;
}
自己出数完全随即就可以了。这样因为自己出的数字是均匀分布,因此理论上对方分析自己的历史数据是完全没有意义的,因为自己下次出哪个跟以前的数据完全无关,概率总是1/5。这样如果对方有学习机的话,就会使他的学习机失效。

因此,只有在双方都使用了学习机的时候,才会因为算法的优劣而影响胜负。

所以,最简单、可靠、聪明的方法,就是完全随即的出牌,并且完全随即的猜测对方的牌。可以保证有50%的胜算。
re: 分享,讨论Programming的习惯 没有昵称 2008-04-25 00:50  
字段与属性的区别竟然是大小写。。。
比较危险。

所以我比较习惯在camel格式的字段前面加下划线,虽然输入时不方便了点,不过安全。
re: 虚函数的调用机制 没有昵称 2008-04-24 11:34  
@信110
经提醒突然有了思路。
两个ToString的偏移是相同的,不过方法的隐含参数“this”不同。很可能是执行base.ToString()时传递的隐含参数决定了执行这一句时使用的虚函数指针表是基类型的,而不是当前类型。这样就可以避免死循环。

中午抽空再仔细看看反汇编代码,现在先认真工作呵呵。
re: 虚函数的调用机制 没有昵称 2008-04-24 11:14  
@Da Vinci
@信110
呵呵,,谢谢两位补充。
本来是想说这里的callvirt并不一定是调用的虚方法,结果描述的不严谨,导致很多错误哈。加上两位的说法就好了。^_^

用call的都是能够明确调用的是哪个方法的;不过对于15楼提到的“为避免循环调用”而使用call,偶还没弄明白呵:
如果ClassA继承object,重写了ToString,ClassB继承ClassA,重写ToString时使用了return base.ToString(),那么下面这句话:
object obj = new ClassB();
obj.ToString();
究竟是怎样避免循环调用的呢?编译器咋知道应该调用的是ClassA.ToString,而不是Object.ToString或者ClassB.ToString?如果说在ClassB的虚函数表中没有更改这个方法的入口,明显是不合理的。因为如果ClassB.ToString在return之前执行了其他操作,那这样处理明显会使得这些操作无效。那么究竟是怎样避免循环调用的呢?思考中。。。

顺便请教两位。^_^
re: 虚函数的调用机制 没有昵称 2008-04-24 10:23  
需要指出的是,上面的IL代码中,全部都是 callvirt 指令而不是 call 指令,之际上如果这里不是虚方法,产生的也是 callvirt 指令,因为他们的区别是如果对象为null,call指令不会产生空引用异常,而callvirt会产生空引用异常。

所以对于引用类型的函数调用,产生的总是callvirt指令,因为需要在调用方法时判断对象是否为空。call指令只会在调用值类型的方法时才会产生,因为值类型的实例永远不会为null。
re: 虚函数的调用机制 没有昵称 2008-04-24 10:13  
从IL代码中根本看不出什么。

我改了下源代码:


public void Fun()
{
ClassA a = null;
ClassB b = null;

a = new ClassA(1);
b = new ClassB(1);

a.ToString();
b.ToString();

a = b;
a.ToString();
}

public class ClassB : ClassA
{
private int _value;

public ClassB(int value) : base(value)
{
this._value = value;
}

public override string ToString()
{
return this._value.ToString();
}


便以后的 IL 代码是这样的:

.method public hidebysig instance void Fun() cil managed
{
// 代码大小 42 (0x2a)
.maxstack 2
.locals ([0] class ConsoleApp.ClassA a,
[1] class ConsoleApp.ClassB b)
IL_0000: ldnull
IL_0001: stloc.0
IL_0002: ldnull
IL_0003: stloc.1
IL_0004: ldc.i4.1
IL_0005: newobj instance void ConsoleApp.ClassA::.ctor(int32)
IL_000a: stloc.0
IL_000b: ldc.i4.1
IL_000c: newobj instance void ConsoleApp.ClassB::.ctor(int32)
IL_0011: stloc.1
IL_0012: ldloc.0
IL_0013: callvirt instance string ConsoleApp.ClassA::ToString()
IL_0018: pop
IL_0019: ldloc.1
IL_001a: callvirt instance string ConsoleApp.ClassB::ToString()
IL_001f: pop
IL_0020: ldloc.1
IL_0021: stloc.0
IL_0022: ldloc.0
IL_0023: callvirt instance string ConsoleApp.ClassA::ToString()
IL_0028: pop
IL_0029: ret
} // end of method Class2::Fun

可以看到IL并没有对虚函数做处理,而是在JIT编译的时候才去处理的。实际上虚函数指针表要保存函数的便宜量,而只有在JIT编译了之后才会知道函数生成的代码段有多大,才会知道函数相对于基址的便宜量。
re: 虚函数的调用机制 没有昵称 2008-04-24 09:58  
@信110
嗯,在生成子类的虚函数指针表时,如果子类没有override父类的虚方法,会把基类对应虚方法的地址拷贝一份放在自己的虚函数指针表中来,而且顺序是跟基类完全一样的。如果子类有新定义的虚函数,会添加在表的后面。

这样就保证了子类的虚函数指针表中的前半部分跟父类的是结构相似的:个数一样、函数顺序一样。这样在整个类层次结构中,就可以保证同一个虚方法在虚函数指针表中的便宜量是相同的。从而实现多态。
re: CLR怎样实现虚方法的多态调用(1) 没有昵称 2008-04-24 09:48  
楼主:
关于这个Table,我有一点疑问。

楼主是否确认非虚函数会写在这个Table中去?我也在很多资料上看过说在.net中这个表里面保存了这些非虚方法,但我对此持怀疑态度,因为没有这个必要。

而且从反汇编的结果来看,对非虚函数的调用也确实是直接指定入口地址的,根本没有经过这个Table。

http://www.cnblogs.com/ILove/archive/2008/04/24/1168454.html
re: CLR怎样实现虚方法的多态调用(1) 没有昵称 2008-04-24 09:44  
@cnfixit
在执行 new Derived ();这句话的时候,就把Derived 类型的虚函数指针表的地址保存在对象中去了。所以指向哪个虚函数指针表是由new 后面这个决定的。
re: CLR怎样实现虚方法的多态调用(1) 没有昵称 2008-04-24 09:41  
@镜涛
父类的虚方法(子类未重载的)确实拷贝到了子类的Table中。否则无法保证同一个虚方法在表中的便宜量相同,也就无法在运行时知道去表中的哪一行去取函数入口地址。
re: 虚函数的调用机制 没有昵称 2008-04-24 09:16  
@李战
调试模式下,“调试——窗口——反汇编”,或者ctrl + alt + d
re: 虚函数的调用机制 没有昵称 2008-04-24 01:31  
@墙头草
看来没说明白。^_^
我也觉得说得不够浅显易懂。慢慢锻炼吧呵。
re: c#中的类型转换详解 没有昵称 2008-04-23 01:15  
“它把简单数据类型通过默认的装箱动作封装成了类”,概念蛮混乱的。
re: C++ c# 分别实现单件模式 没有昵称 2008-04-23 01:08  
lock (lockObj)
{
if (instance == null)
{
instance = new Singleton();
}
}
最好改成:


if (instance == null)
{
lock (lockObj)
{
if (instance == null)
{
instance = new Singleton();
}
}
}

否则每次访问都会lock,会造成额外的开销。
re: 浅谈C#基本数字数据类型。 没有昵称 2008-04-22 18:44  
short b = a编译不通过的原因,是a是整型,整型的取值范围大于short,将a的值复制给b时会造成截断。所以编译器会产生一个错误,要求你使用强制类型转换。实际上也就是提示你:你应该在代码中保证a的值在short类型的取值范围内。否则试想,如果a = 32768,你执行b = a,你觉得b的值会是多少?

short b = 10能够编译通过的原因,是编译器知道10是一个有效的short值,在-32,768 到 32,767之间。如果你写了一句short b = 32768,仍然会出编译错误。

至于你怀疑为什么short b = a不行而short b = 10却没问题,可以看出你有个基本概念不清楚:虽然a = 10,但这两句话是绝对不一样的。第二句话产生的cup指令是“将常数10 赋值到b所在的16位内存地址(因为是short)上去”,而第一句产生的cpu指令是“1、从a所在的32位(因为a是int类型)内存中把数据读出来;2、把这个数值复制给b所在的16位内存地址上去”。

因此可见你对汇编的知识已经忘的差不多了吧。在编程的时候,要用计算机的思维方式去思考,而不是用人的思维方式去思考。

既然你已经在观察IL代码了,那何不观察一下short b = a和short b = 10所产生的IL代码有何不同?
re: .Net,你究竟有多慢 没有昵称 2008-04-17 22:51  
呵呵,,,好像很多朋友在这里研究起来谁快谁慢的问题了,呵呵,离题了离题了。

不过,既然这个问题这么敏感,那我就顺便贴两个地址,各位可以看一下这位仁兄在遇到问题的时候是怎样处理的。
先看这个:http://www.cnblogs.com/wuchang/archive/2006/12/07/584997.html
再看这个:http://eparg.spaces.live.com/blog/cns!59bfc22c0e7e1a76!2274.entry

这位仁兄的做法很值得我们思考。他在发现问题的时候第一反应是去分析问题找原因,并最终拨开迷云找到了事情的真相。相信也正是这样的探索精神让这位仁兄成为一个大牛的。
@Da Vinci
楼主太客气了。用“交流”,别用“指点”哈。
re: .Net,你究竟有多慢 没有昵称 2008-04-17 22:20  
@研究者
er,,,我确实是仔细的看了两天资料确认了之后才写出来的啊。
不过如果帅哥觉得我说的不对,你可以告诉我错在哪里么?我也好继续学习。
re: .Net,你究竟有多慢 没有昵称 2008-04-17 15:22  
@随风逝去(叶进)
我觉得,第一,可以让程序少启动,不过这个适用范围不大;另一个就是多用“延迟加载”。
re: .Net,你究竟有多慢 没有昵称 2008-04-17 14:32  
@路人小刀
整理的很清晰哈。^_^

其实这里面的第六步,“将控制跳转到这里”之前,即时编译器需要把入口函数从IL代码编译成CPU指令,然后才能跳转过去。文章里面讲到这个的时候还没提到即时编译,当时就没指出呵。^_^
嗯。C++里面默认的值类型也容易误用。

C++里面的参数传递默认都是按值拷贝的方式传送的,因此C++里面有个拷贝构造函数,他其实跟.net中的克隆完成同样的工作。
C++里面如果没有正确的理解参数传递的规则,可能会造成不必要的开销。比如下面这段代码:
public MyClass Fun1(MyClass obj)
{
return obj;
}
MyClass B = new MyClass();
MyClass A = Fun1(B);

当执行最下面这句的时候,其实里面会有好多次拷贝(不考虑编译器优化):
第一次,将B这个对象拷贝一份,push到函数堆栈的参数区;
第二次,执行return obj的时候,会把参数区的这个MyClass对象拷贝一份放在函数的返回点上;
第三次,执行A = ***的时候,要把函数返回点上的MyClass对象拷贝一份,复制给A。
这个过程从字面上可能看不出来,因此如果使用不当就会造成类似的额外开销。

如果这里换成是地址引用,就不会有这种问题了——无非是指针的三次拷贝而已。
re: .Net,你究竟有多慢 没有昵称 2008-04-17 13:59  
@李战
和非托管程序比。不管是c、c++、vb、vc等等,他们生成的winapp的编译、加载过程都是一样的。
偶想说的重点是通过比较他们的加载过程和编译过程,了解.net为啥这么慢,而不是比较谁快谁慢的问题呵。^_^
re: .Net,你究竟有多慢 没有昵称 2008-04-17 13:58  
@Da Vinci
帅哥太客气啦~~~java我不熟悉,这个不清楚呵。
偶现在还没来得及接触java。我搞.net之前是搞VC的,一直都没脱离windows平台。其实我的一些底层的知识也是在原来搞VC的时候学到的。^_^

原本打算准备学习一下java的源代码,不过因为要学的东西太多,还没开始呵。。
re: .Net,你究竟有多慢 没有昵称 2008-04-17 12:36  
@Angel Lucifer
是啊,原来的指针指来指去的,给人感觉非常爽。指针这玩意儿在有些人手里会误伤自己,在另外一些人的手里就会威力无比。

.net为了把这个双刃剑变成安全的,耗费了很多性能上的东西来保证安全性。不过现在硬件的发展已经可以弥补这些了。楼上也有很多兄弟说.net不慢,不过在几年前的pc配置上,那叫一个痛苦啊。。。

其实讨论这个问题,也是为了给一部分程序员一个答案:有些人会视.Net为洪水猛兽,提到.net就以慢为理由来抵制。事实上那百分之几的性能差别,在目前的大部分应用中都不是主要矛盾。
re: .Net,你究竟有多慢 没有昵称 2008-04-17 11:29  
@PerfectDesign

呵呵。了解这些的原因就是为了知其所以然,然后更好的发挥.net的长处、避免其短处。仅此而已。没有说发现他有点慢就不用。^_^

c有c的快,快在执行速度;.net有.net的快,快在开发效率。
re: .Net,你究竟有多慢 没有昵称 2008-04-17 09:33  
冤枉啊。
那个美女偶不认识撒。

偶现在还是属于可怜没人要的那种。
re: .Net,你究竟有多慢 没有昵称 2008-04-17 09:26  
@Justin
哈哈,偶技穷了呵。这东东专业术语蛮多的,我还真不知道咋弄个通俗点的东西描述呵。
re: Ankh菜单删除 没有昵称 2008-04-11 00:14  
我靠。鸟svn,搞得我折腾了一天一肚子火,到后面才发觉svn验证密码那里,用户名是大小写敏感。我ft了,这辈子第一次见用户名大小写敏感的系统。
也不知道哪位大侠写的这个模块。
发一个效果图出来?^_^
请教个问题。

这里是这些枚举的值。
public enum DriveType : sbyte
{
CDRom, // 0
Fixed = -2,
Network,// -1
NoRootDirectory = -1,
Ram,// 0
Removable = Network * NoRootDirectory,// 1
Unknown// 2
}

我用下面的代码调用:
DriveType a;
a = (DriveType)(-1);
Console.WriteLine(a);
a = (DriveType)0;
Console.WriteLine(a);


输出结果是:
NoRootDirectory
Ram

为何 (DriveType)(-1)得到的是NoRootDirectory 而不是 Network?
为何 (DriveType)0 得到的是 Ram 而不是 CDRom?
等待源代码。呵呵。
re: 《你必须知道的.NET》到货了 没有昵称 2008-04-08 23:02  
有没有例章看看?
re: Unity(三):快速入门 没有昵称 2008-04-08 22:53  
哈哈,大家进来都发现楼主的编辑器漂亮了,^_^
re: .Net的序列化和反序列化 没有昵称 2008-04-08 22:48  
序列化只是实现这种需求的千千万万种方法中的一个。
re: .Net的序列化和反序列化 没有昵称 2008-04-08 22:47  
貌似题目跟文章内容不符呵呵。。。
re: 控件之ViewState 没有昵称 2008-04-08 14:14  
Viewstate属性能装载的数据类型还是非常多的吧,只要加了SerializableAttribute标签的类都可以。即便遇到别人没注意没打标签的,弄个Wrapper继承一下或者包含一下,在Wrapper上打个标签就又可以了。
re: 在.Net中使用异步(二) 没有昵称 2008-04-08 11:25  
@yellowyu

注意这句话:Console.WriteLine("a={0}, b={1}", nA, nB); ,是在线程函数里面的。所以,这个测试跟同步还是异步是没有关系的。

他证明了,只有当这个函数返回之后,out 参数和ref参数的值才会被修改。

函数返回值、out参数、ref参数都是通过弹堆栈的方式实现的,函数内部会把out参数、ref参数、返回值放在函数堆栈的一个“返回点”上,等到函数执行完毕了之后,系统再把函数堆栈的返回点上的东西复制给外面的变量,然后销毁函数的堆栈。
re: 理解 Thread.Sleep 函数 没有昵称 2008-04-08 11:15  
--引用--------------------------------------------------
风海迷沙: 有点明白了,程序假死与CPU100%也是有区别的。
通常我们执行一个有死循环的程序时,程序窗口界面会变成白色,鼠标移上去显示忙的状态,那是因为程序自身无法响应windows_paint消息事件,无法对界面进行刷新。
而CPU100%时还是可以对程序进行一些操作的,即使有一些后台执行的进程。
不知道有没有说到点上。
--------------------------------------------------------
嗯,没错。假死也有不同情况。有可能是进程中的主要线程被挂起或者其他原因,无法正常的处理消息队列了,这种情况一般CPU使用率还是正常的,其他程序也运行的很好,唯独这个程序的UI不行了。也有可能是某个线程长时间占用CPU,比如大循环,这样系统中的其他线程就没办法得到足够的CPU资源,于是整个操作系统都会变得反应迟钝。这时候CPU使用率很高,因为一直被这个循环使用着。

遇到某个线程在执行死循环,我们仍然有机会使用任务管理器结束掉占用CPU使用率高的进程,原因就是这个时候虽然线程从来没有主动挂起或Sleep过,但是操作系统仍然会强制挂起他。这样“任务管理器”所拥有的线程才有机会获取CPU控制权从而杀死陷入死循环进程。

其实这里也可以看出,“任务管理器”是拥有更高级别的,因为这时候整个系统都反映迟钝了、其他程序都无论怎么点都没反映了,但我们还是能够打开任务管理器结束进程。看一下系统的“csrss”进程,他的优先级是“高”哦,会很容易获得cpu控制权。如果想试验,你可以写个程序把优先级设置为“实时”然后写个循环,再去试任务管理器,就不灵了,^_^
共2页: 1 2 下一页