装配中的脑袋

用程序装配大脑,再用大脑装配程序
随笔 - 118, 评论 - 1214, 引用 - 11

导航

关于

如果想发较大的信件,请用Ninputer @ gmail.com

不要在我的Blog评论中张贴广告,除非同意向我付款。

标签

每月存档

最新留言

广告

怎样让你的密码字符显示为XP的黑色圆球

Windows XP将密码符号由以前版本的*改成了黑色圆球形。但是默认情况下我们自己程序中的密码文本框无法自动显示这种圆球,我在网上找了以下几种解决方案:

方案一:

Windows XP用的“黑色圆球”其实是Unicode字符25CF,因此将PasswordChar换成这个字符就行了:

textBox3.PasswordChar = '\u25CF';

这样显示出来和Windows自带程序的效果是一样的,但缺点是在Windows98等老系统上就会工作不正常。

方案二:

将PasswordChar属性设置成“l”(小写的字母L),然后将文本框的字体改成“Wingdings”。这也会将输入的字符显示为一种黑色圆球,但它比Windows自带程序的所用的圆球要大一点。

这种方法在Windows 98下也能用,而且也是圆球型。

方案三:

前两种方法共同的缺陷就是,不能自动适应系统默认的密码字符,保不准下一版本的Windows就用五角星或者3D图形什么的了。所以这个方法可能是最好的了:.NET Framework 2.0中的文本框提供了UseSystemPasswordChar属性,用了它就可以确保你的密码字符与当前系统默认的一样了。不过我不知道它是怎样实现的,回家以后再研究吧。

下面是一些效果截图:

posted on 2004-09-23 12:59:00 by Ninputer  评论(2) 阅读(3253)

从Tech Ed会场疲倦归来

由于身体不适,今天在会场上的状态极为不佳,只听了孙展波的DEV313和一个微软测试的课就回家了。听孙展波课程唯一的非技术收获就是这个了:)

因为发烧,实在没力气写技术文章,希望开心大哥原谅。病好后一定加倍补上。

posted on 2004-09-18 20:40:00 by Ninputer  评论(7) 阅读(1700)

今天看到mvm(吗?)

今天早上,Tim带着一个酷似传说中mvm的人到我们面前,介绍说他叫“郑子颖”。我当时就产生一种深邃的熟悉感……。难道真是mvm?来到ATC工作了?

posted on 2004-09-13 16:31:00 by Ninputer  评论(19) 阅读(2243)

对Framework 2.0 BETA1的类型参数对象方法调用很满意

记得在Framework 2.0还叫1.2的时候,我曾经进行过几个简单的实验,以便测试对带有约束的泛型类中,类型参数对象的方法调用的性能。其结果令我非常失望——类型参数对象的方法调用比用接口调用甚至通过Object传递的方式都慢得多,泛型的优势完全没有体现出来。到了BETA1,我又可以重复这个简单的实验,结果却大大不同了。这是我的四个实验方法:

Private Sub Test1(Of T As ITest)(ByVal obj As T)
    obj.Test()
End Sub

Private Sub Test2(ByVal obj As ITest)
    obj.Test()
End Sub

Private Sub Test3(ByVal obj As Object)
    DirectCast(obj, TTest).Test()
End Sub

Private Sub Test4(ByVal obj As TTest)
    obj.Test()
End Sub

其中用到的结构及接口定义如下:

Private Interface ITest
    Sub Test()
End Interface

Private Structure TTest
    Implements ITest

    Public i As Integer

    Public Sub Test() Implements ITest.Test
        'no code
    End Sub
End Structure

很简单,第一个方法用了约束ITest的类型参数T作为参数;第二个是用ITest接口作为类型参数;第三个方法则是用Object作为参数,并在调用前直接拆箱;第四个直接用结构作为类型参数,想象中应该是它最快……测试用的代码已经是老生常谈了:

Dim w As New Stopwatch

'Static 让所有测试共享一个预先创建结构的实例

Static testObj As New TTest

w.Start()
For iLoop As Integer = 0 To 10000000

    Test1(testObj) 'Or Test2, Test3, etc

Next
w.Stop()

TextBox1.AppendText(w.ElapsedMilliseconds & vbCrLf)

结果为Release下,不开特殊优化,预运行10次得到的(毫秒):

泛型:208
接口:394
Object:329
直接结构:209

我也很震惊,早先性能很差的泛型版本竟然超过了直接结构调用!而接口参数的速度反而成了最慢。我对这几个月来,.NET Framework组在泛型性能上的工作十分满意,但愿在正式版还有上佳表现。

posted on 2004-09-07 21:49:00 by Ninputer  评论(4) 阅读(1764)

Visual Basic 2005新功能点评(二十一)——泛型 part.2

尽管在周末发帖子不符合sumtec的Blog守则,但我确实无从选择。每天6点多出家门8点到家10点睡觉的生活,让我找不出空余时间来写Blog。我只能尽量用周末的时间为我贫乏的Blog补充几篇帖子。

今天我继续讨论泛型。上次我们已经了解到.NET泛型在减少装箱和编译时类型检查方面的优点。今天我们继续深入泛型给.NET开发带来的变化。

泛型的类型系统

泛型类型(Generic Type)通过赋予类型参数,在使用时可以表现为多种构造类型(Constructed Type)。如TheClass(Of T)在使用时可以是TheClass(Of Int32),也可以是TheClass(Of String)他们都是不同的类型。这些类型之间没有任何继承关系,也没有互相包容的功能。TheClass(Of Object)并不是其他TheClass(Of T)构造类型的基类,也没有一种写法可以表示类型参数为任意类型的情况。这种类型衍生往往会连带泛型类内嵌类型一起衍生。比如在TheClass(Of T)中内嵌定义有枚举(或结构、委托、类等)TypeA,则TheClass(Of Int32).TypeA和TheClass(Of String).TypeA也非相同类型。在.Net Framwork的类库中,这种情形频繁出现,如List(Of T).Enumerator。因此,注意让你的内嵌类性与泛型的类型参数有关,否则就应该将内嵌类型定义到泛型类型的外部,以免发生类型衍生。一般不要在泛型类型中内嵌定义另一个泛型类型,如ClassA(Of T1).ClassB(Of T2),他在衍生类型的时候就更复杂了,因为两个类型参数都可以赋予不同的类型,会产生大量你也不知道有什么用的构造类型。

.NET Framework还增强了反射的功能以便在运行时研究泛型类型及其所有构造类型。每个构造类型都有确定的类型,可以通过obj.GetType()获取运行时类型的Type对象,还可以用GetType运算符获取泛型类型本身或其任何构造类型的Type对象。现在Type类有HasGenericParameters属性以指示此类型是否源自泛型类型,以及HasUnboundGenericParameters属性以指示此泛型类型的所有类型参数是否已经确定等。你还可以通过Type对象的相关方法检测泛型类型每个类型参数的详细状况。

约束

约束(Constraint)这一功能的本意是缩小类型参数所能取值的范围。比如你希望你的类ClassA(Of T)中类型参数T只能接受Exception或其子类等要求,可以通过约束这一功能达成。约束会带来一种“副作用”,事实上更多人把这个副作用当成约束的主要功能来用,我们下边详细叙述。约束的语法是:

Definition(Of TypeParam As Constraints)

比如我们要给ClassA定义类型参数T,并约束T只能为Exception或其子类的定义为:

Class ClassA(Of T As Exception)

如果我们要写ClassA(Of Integer)就会产生编译错误,因为T已经不能去Int32作类型参数了。T的取值范围已经缩小,除此之外约束还有什么功能呢。我们可以在ClassA中定义一个方法:

Public Sub ThrowIt(ByVal ex As T)
    Throw ex
End Sub

我们写了Throw ex,为什么可以这样写?可以试试将类型定义中的“As Exception”去除,这里立即就会有编译错误。这是因为.NET默认情况下不允许对类型参数的对象施以任何操作,除了能对Object类型进行的操作以外。就是说默认情况下T类型的对象没有除Object类型所具有的方法/属性以外的任何成员,也不能使用任何运算符。这通常是一个很大的限制。但当你使用约束时,类型参数就会自动具有继承自约束类型的所有功能。比如继承自Exception就可以用于Throw语句,而约束了Exception的类型参数T的对象同样可以用于Throw语句。我们常常这样写:

Class ClassB(Of T As IDisposable)

这样T的取值范围就被限定在实现了IDisposable的所有类型中,而副作用是T型对象具有IDisposable接口的成员:Dispose()方法。比如书写这样的过程。

Public Sub DisposeIt(ByVal obj As T)
    obj.Dispose()
End Sub

我要强调约束的主要功能是减少类型参数的取值范围,而不是给类型参数增加可操作的功能(那只是副作用)。一般不要为了这种目的给类型参数加约束。比如你想让操作对象有Dispose方法,不妨用这种写法代替约束:

Public Sub DisposeIt(ByVal obj As IDisposable)
    obj.Dispose()
End Sub

只有当你的类型参数一定要有某种功能,否则整个泛型类都无法工作的时候,才使用约束。不然你会发现约束了很多类型后,你的泛型类型的用途大大减少了。

还有一种特殊的约束——构造器约束。他约束你的类型参数只能取那些有一个不带参数的公有构造器的类型。其副作用是,你可以在这个泛型类中创建类型参数的实例:

Public Class ClassB(Of T As New)
    Public Sub MySub()
        Dim o As T
        o = New T()
    End Sub
End Class

注意构造器的写法:用New关键字作约束类型。构造器约束看起来很有用。

如果你要约束两个以上的类型,你可以把要约束的类型放在花括号里{},就像数组一样。比如你的类型参数同时需要约束构造器和IDisposable,就这样写:

Public Class ClassC(Of T As {IDisposable, New})

你还可以用多约束做一些以前只用接口做不到的事情,比如这样:

Sub MyMethod(Of T As {IDisposable, ICloneable})(ByVal obj As T)

这个定义实现了让参数obj的类型只能为同时实现了两个接口的类型,不用泛型你以前可以做到吗?

下期介绍:

泛型API

posted on 2004-09-04 11:35:00 by Ninputer  评论(8) 阅读(3754)

Powered by: Joycode.MVC引擎 0.5.2.0