提问人:Jakub Šturc 提问时间:8/23/2008 最后编辑:Orion EdwardsJakub Šturc 更新时间:4/8/2015 访问量:5891
为什么 String.Format 是静态的?[关闭]
Why is String.Format static? [closed]
问:
比较
String.Format("Hello {0}", "World");
跟
"Hello {0}".Format("World");
为什么 .Net 设计人员选择静态方法而不是实例方法?你觉得怎么样?
答:
我认为这是因为它是一种创建者方法(不确定是否有更好的名字)。它所做的只是接受你给它的东西并返回一个字符串对象。它不对现有对象进行操作。如果它是非静态的,则需要一个字符串作为开头。
因为 Format 方法与字符串的当前值无关。不使用字符串的值。它接受一个字符串并返回一个。
我认为它是静态的没有错。
静态方法的语义对我来说似乎更有意义。也许是因为它是原始的。在经常使用基元的地方,您希望使使用它们的实用程序代码尽可能轻。此外,我认为 String.Format 的语义比“MyString BLAH BLAH {0}”要好得多。格式 ...
评论
"my {0} string".Format(args)
当您有一个维护某种状态的对象时,实例方法很好;格式化字符串的过程不会影响您正在操作的字符串(阅读:不修改其状态),它会创建一个新字符串。
使用扩展方法,您现在可以吃蛋糕并吃掉它(即,如果后一种语法可以帮助您在晚上睡得更好,则可以使用后者语法)。
我还没有尝试过,但你可以为你想要的东西制作一个扩展方法。我不会这样做,但我认为它会起作用。
此外,我发现更符合其他模式化静态方法,如 、 等。String.Format()
Int32.Parse()
long.TryParse()
如果你想要一个非静态格式,你也可以使用一个。StringBuilder.AppendFormat()
StringBuilder
String.Format
至少接受一个 String 并返回另一个 String。它不需要修改格式字符串即可返回另一个字符串,因此这样做意义不大(忽略它的格式)。另一方面,成为成员函数不会有太大的延伸,除了我认为 C# 不允许像 C++ 那样的常量成员函数。[如果是这样,请纠正我和这篇文章。String.Format
我认为使用 String.Format 通常看起来更好,但是当您已经将字符串存储在要“格式化”的变量中时,我可以看到想要拥有非静态函数的意义。
顺便说一句,string 类的所有函数都不会作用于字符串,而是返回一个新的字符串对象,因为字符串是不可变的。
评论
String.Format
Trim
PadLeft
因为 Format 方法与字符串的当前值无关。
这适用于所有字符串方法,因为 .NET 字符串是不可变的。
如果它是非静态的,则需要一个字符串作为开头。
它确实是:格式字符串。
我相信这只是 .NET 平台中许多设计缺陷的另一个例子(我并不是说这是火焰;我仍然发现 .NET 框架优于大多数其他框架)。
评论
String.Format 必须是静态方法,因为字符串是不可变的。使其成为实例方法意味着您可以使用它来“格式化”或修改现有字符串的值。这是你做不到的,让它成为一个返回新字符串的实例方法将没有意义。因此,它是一种静态方法。
评论
好吧,我想你必须对它相当讲究,但就像人们所说的那样,由于隐含的语义,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.
评论
"a b c".Replace("a", "kitty")
也许 .NET 设计者这样做是因为 JAVA 这样做的......
拥抱和延伸。:)
请参见:http://discuss.techinterview.org/default.asp?joel.3.349728.40
评论
当我升级到 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
- 当时写它的人主观上更喜欢它。
我真的找不到任何其他正当理由
评论
.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.
评论
将实例作为第一个变量的非重载、非继承的静态方法(如 Class.b(a,c))在语义上等同于方法调用(如 a.b(c)),因此平台团队做出了任意的、审美的选择。(假设它编译为相同的 CIL,它应该编译。唯一知道的方法就是问他们为什么。
他们这样做可能是为了让两个字符串在词典上彼此靠近,即
String.Format("Foo {0}", "Bar");
而不是
"Foo {0}".Format("bar");
您想知道索引映射到什么;也许他们认为“.格式“部分只是在中间增加了噪音。
有趣的是,ToString 方法(至少对于数字而言)正好相反:number。ToString(“000”) 格式字符串位于右侧。
.NET 字符串是不可变的
因此,拥有实例方法完全没有意义。
按照这个逻辑,字符串类不应该有返回对象的修改副本的实例方法,但它有很多(Trim、ToUpper 等)。此外,框架中的许多其他对象也这样做。
我同意,如果他们要使其成为实例方法,这似乎是一个不好的名字,但这并不意味着该功能不应该是实例方法。Format
为什么不这样呢?它与 .NET Framework 的其余部分一致
"Hello {0}".ToString("Orion");
@Jared:
将实例作为第一个变量的非重载、非继承的静态方法(如 Class.b(a,c))在语义上等同于方法调用(如 a.b(c))
不,他们不是。
(假设它编译为相同的 CIL,它应该编译。
那是你的错误。产生的CIL是不同的。区别在于不能对值调用成员方法,因此 CIL 会插入针对值的检查。这显然不是在静态变体中完成的。null
null
但是,不允许值,因此开发人员必须手动插入检查。从这个角度来看,成员方法变体在技术上会更胜一筹。String.Format
null
评论
我实际上不知道答案,但我怀疑这与直接在字符串文字上调用方法有关。
如果我没记错的话(我实际上没有验证这一点,因为我手边没有旧的 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 设计者正试图再次避免这种情况。
评论
"".Format
这是为了避免与方法混淆。.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);
我不知道他们为什么要这样做,但这已经不重要了:
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);
}
}
恕我直言,这要容易得多。
另一个原因是与 C 函数的相似性。它应该让 C 开发人员更容易切换语言。String.Format
printf
C# 的一大设计目标是尽可能轻松地从 C/C++ 过渡到 C/C++。对于只有 C/C++ 背景的人来说,在字符串文字上使用点语法看起来非常奇怪,而格式化字符串是开发人员在使用该语言的第一天可能会做的事情。所以我相信他们让它静止,让它更接近熟悉的领域。
我认为这是因为 Format 本身不采用字符串,而是采用“格式字符串”。大多数字符串都等同于“Bob Smith”或“1010 Main St”之类的东西,而不是“Hello {0}”,通常只有在尝试使用模板创建另一个字符串(如工厂方法)时才放入这些格式字符串,因此它本身就适合静态方法。
评论