为什么String.Format是静态的?

时间:2008-08-22 19:15:09

标签: .net string

比较

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

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

.Net设计师为什么选择静态方法而不是实例方法?你觉得怎么样?

22 个答案:

答案 0 :(得分:48)

  

因为Format方法与字符串的当前值无关。

对于所有字符串方法都是如此,因为.NET字符串是不可变的。

  

如果它是非静态的,你需要一个字符串开始。

它确实:格式字符串。

我认为这只是.NET平台中许多设计缺陷的另一个例子(我并不认为这是一个火焰;我仍然发现.NET框架优于大多数其他框架)。

答案 1 :(得分:28)

我实际上并不知道答案,但我怀疑它与直接调用字符串文字方法的方面有关。

如果我没记错的话(我实际上没有验证这个,因为我没有旧的IDE方便),早期版本的C#IDE无法在IntelliSense中检测针对字符串文字的方法调用,这会产生很大的影响关于API的可发现性。如果是这种情况,输入以下内容将不会给您任何帮助:

"{0}".Format(12);

如果您被迫键入

new String("{0}").Format(12);

很明显,使Format方法成为实例方法而不是静态方法没有任何好处。

.NET库是由很多给我们MFC的人设计的,而String类特别与MFC中的CString类非常相似。 MFC确实有一个实例Format方法(使用printf样式格式代码而不是.NET的大括号样式),这很痛苦,因为没有CString文字这样的东西。所以在我工作的MFC代码库中,我看到了很多:

CString csTemp = "";
csTemp.Format("Some string: %s", szFoo);

这很痛苦。 (我不是说上面的代码即使在MFC中也是很好的做法,但这似乎是项目中大多数开发人员学习如何使用CString :: Format的方式)。根据这一传统,我可以想象API设计师试图再次避免这种情况。

答案 2 :(得分:9)

嗯我想你必须要特别注意它,但就像人们所说的那样,由于隐含的语义,String.Format更有意义。考虑:

"Hello {0}".Format("World"); // this makes it sound like Format *modifies* 
                             // the string, which is not possible as 
                             // strings are immutable.

string[] parts = "Hello World".Split(' ');    // this however sounds right, 
                                             // because it implies that you 
                                             // split an existing string into 
                                             // two *new* strings.

答案 3 :(得分:8)

当我升级到VS2008和C#3时,我做的第一件事就是这样做

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

所以我现在可以从

更改我的代码了
String.Format("Hello {0}", Name);

"Hello {0}".F(Name);

我当时更喜欢。 现在(2014)我不打扰因为再次添加到我创建的每个随机项目或链接到一些bag-of-utils库中只是另一个麻烦。

至于.NET设计师选择它的原因是什么?谁知道。这似乎完全是主观的。 我的钱都在

  • 复制Java
  • 当时写作的人主观地喜欢它。

我找不到任何其他正当理由

答案 4 :(得分:6)

我认为这是因为Format本身不接受字符串,而是“格式字符串”。大多数字符串都等于“Bob Smith”或“1010 Main St”之类的东西或者你有什么而不​​是“Hello {0}”,通常你只是在尝试使用模板创建另一个时才放入那些格式字符串。 string,就像工厂方法一样,因此它将自己赋予静态方法。

答案 5 :(得分:4)

我认为这是因为它是一种创作者方法(不确定是否有更好的名字)。它所做的就是拿你给它的东西并返回一个字符串对象。它不对现有对象进行操作。如果它是非静态的,那么你需要一个字符串开始。

答案 6 :(得分:4)

也许.NET设计师这样做是因为JAVA这样做了......

拥抱并延伸。 :)

请参阅:http://discuss.techinterview.org/default.asp?joel.3.349728.40

答案 7 :(得分:4)

因为Format方法与字符串的当前值无关。不使用字符串的值。它需要一个字符串并返回一个。

答案 8 :(得分:3)

  

.NET字符串是不可变的   因此,使用实例方法绝对没有意义。

通过该逻辑,字符串类应该没有返回对象的修改副本的实例方法,但它具有 lots (Trim,ToUpper等)。此外,框架中的许多其他对象也是这样做的。

我同意如果他们要使它成为一个实例方法,Format似乎是一个坏名称,但这并不意味着该功能不应该是一个实例方法。

为什么不呢?它与the rest of the .NET framework

一致
"Hello {0}".ToString("Orion");

答案 9 :(得分:2)

我认为使用String.Format一般看起来更好,但是当你已经将一个字符串存储在你想要“格式化”的变量中时,我可以看到想要拥有非静态函数的一点。

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

答案 10 :(得分:2)

C#的一个重要设计目标是尽可能简单地从C / C ++过渡到它。在字符串文字上使用点语法对于只有C / C ++背景的人来说看起来很奇怪非常,并且格式化字符串是开发人员在第一天使用该语言可能会做的事情。所以我相信他们让它更接近熟悉的领域。

答案 11 :(得分:2)

String.Format的另一个原因是与来自C的函数printf的相似性。它应该让C开发人员更容易切换语言。

答案 12 :(得分: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);
    }
}

这很容易,恕我直言。

答案 13 :(得分:2)

这是为了避免与.ToString()方法混淆。

例如:

double test = 1.54d;

//string.Format pattern
string.Format("This is a test: {0:F1}", test );

//ToString pattern
"This is a test: " + test.ToString("F1");

如果Format是字符串上的实例方法,这可能会导致混淆,因为模式不同。

String.Format()是一种将多个对象转换为格式化字符串的实用工具方法。

字符串上的实例方法对该字符串执行某些操作。

当然,你可以这样做:

public static string FormatInsert( this string input, params object[] args) {
    return string.Format( input, args );
}

"Hello {0}, I have {1} things.".FormatInsert( "world", 3);

答案 14 :(得分:2)

@Jared:

  

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

不,他们不是。

  

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

那是你的错。产生的CIL是不同的。区别在于无法在null值上调用成员方法,因此CIL会对null值进行检查。这显然不是在静态变体中完成的。

但是,String.Format 允许null值,因此开发人员必须手动插入检查。从这个角度来看,成员方法变体在技术上是优越的。

答案 15 :(得分:2)

当你有一个维持某种状态的对象时,实例方法很好;格式化字符串的过程不会影响您正在操作的字符串(读取:不修改其状态),它会创建一个新字符串。

使用扩展方法,你现在可以吃蛋糕了(也就是说,如果它可以帮助你在晚上睡得更好,你可以使用后一种语法)。

答案 16 :(得分:1)

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

可能他们这样做是为了保持两个字符串彼此靠近,即。

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

而不是

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

您想知道索引映射到的内容;也许他们认为“.Format”部分只会在中间添加噪音。

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

答案 17 :(得分:1)

我认为它是静态的没什么不对。

静态方法的语义似乎对我更有意义。也许是因为它是原始的。在经常使用基元的情况下,你想让实用程序代码尽可能地使用它们。而且,我认为使用 String.Format 而不是的语义要好得多。 MyString BLAH BLAH {0}“。格式 ...

答案 18 :(得分:1)

我还没有尝试过,但您可以根据需要制作扩展方法。我不会这样做,但我认为它会起作用。

此外,我发现String.Format()更符合其他图案化静态方法,例如Int32.Parse()long.TryParse()等。

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

答案 19 :(得分:0)

String.Format必须是静态方法,因为字符串是不可变的。使它成为实例方法意味着您可以使用它来“格式化”或修改现有字符串的值。这是你做不到的,并且使它成为返回新字符串的实例方法是没有意义的。因此,这是一种静态方法。

答案 20 :(得分:-1)

String.Format至少获取一个String并返回不同的String。它不需要修改格式字符串以返回另一个字符串,因此这样做没有意义(忽略它的格式)。另一方面,使String.Format成为成员函数并不是一个很大的延伸,除了我不认为C#允许像C ++这样的const成员函数。 [如果确实如此,请纠正我和这篇文章。]

答案 21 :(得分:-2)

.NET字符串是不可变的

因此,使用实例方法绝对没有意义。

String foo = new String();

foo.Format("test {0}",1); // Makes it look like foo should be modified by the Format method. 

string newFoo = String.Format(foo, 1); // Indicates that a new string will be returned, and foo will be unaltered.