不可变的Dot Net字符串

3

我通常会在VB.NET中将我的字符串变量定义为:

Dim f_sName as string=String.Empty
f_sName = "foo"

在 .net 中,由于字符串的不可变性质,有没有更好的方式来初始化字符串并处理 "Variable 'f_sName' is used before it has been assigned a value. A null reference exception could result at runtime." 警告?

对于那些没有接受无参数构造函数的类,比如 System.Net.Sockets.NetworkStream,最好的定义和初始化该类型变量的方法是什么?

3个回答

3

这与字符串不可变无关。

更好的模式是:

 Dim f_sName as string = "Foo"

但这取决于情况,如果你能使用它。

同样适用于使用Nothing或Empty进行初始化。如果您想尽早捕获错误,则:

  1. 根本不要初始化。 "变量'xxx'在分配值之前被使用"是您的朋友,而不是敌人。
  2. 使用Nothing进行初始化。 它也可能会暴露错误。
  3. 使用Empty进行初始化(或只是“”,没有区别)。

对于像NetworkStream这样的类,同样的事情:在需要时不要创建实例并且不要声明变量。 对于像NetworkStream这样的可处置类,这意味着使用Using子句:

 Using fs As New NetworkStream(....)

 End Using

在那个狭窄的范围之外,让'fs'可用既不可取也不实用。


如果我们遵循只在需要时声明变量的哲学,那么这是否意味着在 try 块中声明的变量将不会在 catch 块中可用? - klork
@klork,是的,我承认这可能是一个有效的问题。但这不应该是一个常规模式。在catch块中,您需要异常对象。如果您发现自己正在处理其他(可丢弃的)对象,则重构为另一个Using和Try / Catch嵌套可能会使整个问题消失。 - H H

1
Dim f_sName as String = Nothing

或者

Dim f_sName As New String()

顺便说一下:将 mixedCase 变量命名与 underscores(如 f_sName)混合使用,大多数情况下看起来很奇怪,这个变量名代表什么意思?

第一个f表示变量的作用域。f = 函数/过程级别,m = 模块级别,g = 全局。下划线只是为了可读性而使用的分隔符。s是变量类型,在这种情况下是字符串。其余字符是描述性标识符,指示字符串的内容。你如何命名你的变量? - klork
1
我在 .net 代码中还没有看到过这种情况(当作用域标识符在移动代码时变得不一致时,看起来很危险)。这可能是一篇有趣的文章:http://10rem.net/articles/net-naming-conventions-and-programming-standards---best-practices - ChristopheD

1

将字符串初始化为null和String.Empty基本上是一样的。个人而言,我认为将其设置为string.empty确实是处理它的最佳方式。将其设置为null会导致抛出空引用异常,而将其设置为String.Empty则不会。

有人可以争论初始化两种方式的优点,但从优化的角度来看,没有明显的区别。


1
从技术上讲,不是同一个概念,但对于大多数人来说它们代表了相同的意思。否则,微软就不会创建ISNullOrEmpty。人们普遍认为它们是可以互换的。你是正确的,将其设置为null会引发空引用异常。 - kemiller2002
但是“相同的想法”并不符合这个特定问题的精神。有时候选择哪一个进行初始化是很重要的。 - H H
如果不是这样,微软就永远不会创建ISNullOrEmpty。我认为微软在.NET 2.0中引入IsNullOrEmpty并不是因为大多数人认为空字符串和空字符串是可以互换的。他们也没有在.NET 4.0中引入IsNullOrWhitespace,因为只包含空格字符的字符串与空字符串是可以互换的。当然,null和空字符串之间的区别有时(不总是)很重要-实际上,对此区别的需求推动了在.NET 2.0中引入可空值类型。 - Joe
@joe:字符串已经是可空的了。再次强调,初始化时确实很重要,NullOrEmpty是硬币的另一面。 - H H

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接