比较
String.Format("Hello {0}", "World");
与
"Hello {0}".Format("World");
.Net设计师为什么选择静态方法而不是实例方法?你觉得怎么样?
答案 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设计师选择它的原因是什么?谁知道。这似乎完全是主观的。 我的钱都在
我找不到任何其他正当理由
答案 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()
等。
如果您想要非静态格式,云也可以使用StringBuilder
。
StringBuilder.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.