为什么String.Format是静态的?

40

比较

String.Format("Hello {0}", "World");

"Hello {0}".Format("World");

为什么 .Net 设计者选择使用静态方法而不是实例方法?您的看法是什么?
22个回答

2

我不知道他们为什么这样做,但现在已经不重要了:

public static class StringExtension
{
    public static string FormatWith(this string format, params object[] args)
    {
        return String.Format(format, args);
    }
}

public class SomeClass
{
    public string SomeMethod(string name)
    {
        return "Hello, {0}".FormatWith(name);
    }
}

我个人认为,这样会更加流畅。

2

当你有一个维护某些状态的对象时,实例方法是很好的选择;格式化字符串的过程不会影响你正在操作的字符串(即不会修改其状态),而是创建一个新的字符串。

使用扩展方法,你现在可以既拥有自己想要的语法,又能达到目的(即如果它能帮助你晚上睡得更好,你可以使用后一种语法)。


2

我认为使用String.Format通常会更好,但如果您已经有一个存储在变量中要“格式化”的字符串,则希望具有非静态函数的点也是可以理解的。

顺便说一下,字符串类的所有函数都不作用于字符串本身,而是返回一个新的字符串对象,因为字符串是不可变的。


但是,让 String.Format 是静态的,而像 TrimPadLeft 这样的其他方法不是静态的是不一致的。 - Alex Lowe

2

@Jared:

不重载,不继承的静态方法(例如Class.b(a,c))将实例作为第一个变量,与方法调用(例如a.b(c))在语义上是等效的。

不,它们并不等价。

(假设它编译成相同的CIL,应该是这样。)

这是你的错误。生成的CIL是不同的。区别在于成员方法不能在null值上调用,因此CIL会插入对null值的检查。而静态方法则没有这个操作。

然而,String.Format不允许null值,所以开发人员必须手动插入检查。从这个角度来看,成员方法变体在技术上更优。


2
当有人(Python)告诉我将成员函数视为带有显式“this”对象作为第一个元素的静态函数时,我认为这是一个非常有用的范例。感谢您对空值的深思熟虑的观点!顺便说一句,重载会给静态/成员方法等价性增加更多复杂性。 - Jared Updike

2
< p >另一个使用String.Format的原因是与C语言中的printf函数相似。它旨在让C开发人员更容易地切换语言。


2
一个重要的 C# 设计目标是尽可能地让从 C/C++ 切换到 C# 变得容易。对于只有 C/C++ 背景的人来说,在字符串文字上使用点语法会看起来非常奇怪,而格式化字符串则是开发人员在开始使用该语言时可能会做的事情。因此,我认为他们将其设置为静态以使其更接近熟悉的领域。

1

我认为将其设置为静态的没有任何问题。

静态方法的语义对我来说更有意义。也许是因为它是一个原始类型。当经常使用原始类型时,您希望使用与它们一起工作的实用程序代码尽可能轻巧。此外,我认为使用 String.Format 要比 "MyString BLAH BLAH {0}".Format 更好。


它是静态的没有问题;我想知道的原因是相比于"my {0} string".Format(args),它增加了长度,并且使得将字符串字面量转换为格式化字符串变得更加复杂。虽然不是很多,但足够使用实例方法来简化操作。 - ehdv

1

我还没有尝试过,但你可以为你想要的内容创建一个扩展方法。我不会这样做,但我认为它会起作用。

另外,我发现String.Format()更符合其他模式化静态方法的风格,比如Int32.Parse()long.TryParse()等。

如果你想要一个非静态格式,你也可以使用StringBuilderStringBuilder.AppendFormat()


1

非重载,非继承的静态方法(例如Class.b(a,c))将实例作为第一个变量,语义上等同于方法调用(例如a.b(c)),因此平台团队做出了任意的审美选择。(假设编译成相同的CIL,应该是这样。)唯一的方法是询问他们为什么。

可能是为了让这两个字符串在字典排序中保持接近,即

String.Format("Foo {0}", "Bar");

替代

"Foo {0}".Format("bar");

你想知道索引映射到什么;也许他们认为“.Format”部分只是在中间添加噪音。

有趣的是,ToString方法(至少针对数字)相反:number.ToString(“000”),格式字符串在右侧。


-1

String.Format 至少需要一个字符串并返回另一个字符串。它不需要修改格式字符串以返回另一个字符串,因此这样做(忽略其格式)没有太多意义。另一方面,将 String.Format 设为成员函数也不是那么困难,只是我认为 C# 不允许像 C++ 那样的常量成员函数。如果我错了,请纠正我和这篇文章。


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