C#在创建字符串后更改字符串
好吧,我知道这个问题非常简单,我承认我对C#也是个新手。但标题并不能描述整个情况,所以请听我说 我需要修改一个URL字符串,该字符串是在C#代码隐藏中创建的,从字符串末尾删除子字符串“.aspx”。所以基本上我知道我的URL,进入这个类,将类似于“Blah.aspx”,我想去掉字符串中的“.aspx”部分。我认为这是很容易做到的,只要找到子字符串,并删除它,如果它存在的话(或一些类似的策略,如果有人有一个优雅的解决方案,如果他们以前认为做过的话,会很感激)。问题是:C#在创建字符串后更改字符串,c#,immutability,C#,Immutability,好吧,我知道这个问题非常简单,我承认我对C#也是个新手。但标题并不能描述整个情况,所以请听我说 我需要修改一个URL字符串,该字符串是在C#代码隐藏中创建的,从字符串末尾删除子字符串“.aspx”。所以基本上我知道我的URL,进入这个类,将类似于“Blah.aspx”,我想去掉字符串中的“.aspx”部分。我认为这是很容易做到的,只要找到子字符串,并删除它,如果它存在的话(或一些类似的策略,如果有人有一个优雅的解决方案,如果他们以前认为做过的话,会很感激)。问题是: “因为字符串是不可变的,所以
“因为字符串是不可变的,所以在创建字符串对象后(如果不使用不安全的代码),不可能修改字符串对象的值。”这是来自MSDN官方网站。所以我现在想知道,如果字符串真的是不可变的,那么我就不能(不应该)在创建字符串之后更改它。那么,我如何确保我计划做的事情是安全的呢?字符串不变性对于正常使用来说不是问题——它只是意味着像“Replace”这样的成员函数,而不是修改现有的字符串对象,而是返回一个新的字符串对象。实际上,这通常意味着您必须记住将更改复制回原始版本,例如:
string x = "Blah.aspx";
x.Replace(".aspx", ""); // still "Blah.aspx"
x = x.Replace(".aspx", ""); // now "Blah"
字符串的奇怪之处在于System.String
继承了System.Object
,但由于其不变性,其行为类似于值类型而不是对象。例如,如果将字符串传递到函数中,则无法修改它,除非通过引用传递:
void Test(string y)
{
y = "bar";
}
void Test(ref string z)
{
z = "baz";
}
string x = "foo";
Test(x); // x is still "foo"
Test(ref x); // x is now "baz"
你不改变字符串,你改变变量。与引用字符串(如
“foo.aspx”
)的变量不同,将其更改为指向值为“foo”
的新字符串
打个比方,在数字2上加一并不会改变数字2。两个仍然和以前一样,您已经将一个变量从一个数字改为另一个数字
对于您的具体情况,EndsWith
和Remove
使其变得足够简单:
if (url.EndsWith(".aspx"))
url = url.Remove(url.Length - ".aspx".Length);
请注意,Remove
取一个字符串,一个整数,并给我们一个全新的字符串,我们需要将它赋回变量。它不会改变字符串本身
还请注意,有一个类可用于解析URL,它将能够处理可能出现的所有复杂情况,包括哈希、查询参数等。您应该使用该类解析出您感兴趣的URL的各个方面。String.Replace()
不会修改字符串。它将创建一个新的。因此,以下代码:
String myUrl = @"http://mypath.aspx";
String withoutExtension = myUrl.Replace(".aspx", "");
将创建一个全新的字符串,该字符串被分配给withoutExtension。C#中的字符串是不可变的,正如您所说。这意味着这将在内存中创建多个字符串对象:
String s = "String of numbers 0";
s += "1";
s += "2";
因此,虽然变量s
将返回数值012
字符串,但在内部它需要在内存中创建三个字符串来完成
在您的特定情况下,解决方案非常简单:
String myPath = "C:\\folder1\\folder2\\myFile.aspx";
myPath = Path.Combine(Path.GetDirectoryName(myPath), Path.GetFileNameWithoutExtension(myPath));
同样,这看起来好像myPath
已经改变了,但实际上没有改变。发生了内部复制和分配,您可以继续使用相同的变量
此外,如果必须保留原始变量,只需创建一个新变量:
String myPath = "C:\\folder1\\folder2\\myFile.aspx";
String thePath = Path.Combine(Path.GetDirectoryName(myPath), Path.GetFileNameWithoutExtension(myPath));
无论哪种方式,最终都会得到一个可以使用的变量
请注意,使用Path
方法可确保获得正确的路径操作,而不是盲目的String
替换,这可能会产生意外的副作用。您不能更改字符串(也不应该更改)。但是您可以轻松地在旧字符串的基础上创建新字符串。调用子字符串时,会为您创建一个新字符串。如果它是“Blah.aspx?query=yup”,结果应该是什么?不幸的是,我刚刚发现该字符串是在离开此类后添加的.aspx。。。所以现在我再一次被困在寻找发生这种情况的地方。我的问题是我使URL看起来像“Blah?ID=100.aspx”,这是不正确的。如果您想对字符串进行大量操作,最好使用一个可变的StringBuilder
。这样可以避免为每个插入/替换操作生成新字符串。在您的情况下,Uri
/UriBuilder
类可能很有用。@mikez这对于小操作来说可能过于昂贵。不管怎么说,复制仍在进行。OP似乎只想在末尾删除它,而不是在任何地方删除它。@Servy在这种情况下,您可以使用正则表达式指定.aspx之后没有任何内容。“.aspx$”就可以了。@KyleRogers你可以,如果你想的话,但那是用大锤打苍蝇。这实际上是我所需要的,所以我选择了这个作为答案。对于下面的内容,我仍将研究各位所说的内容,并感谢各位的评论。String
在任何意义上都不像值类型。它是一种引用类型,在所有情况下的行为都类似于引用类型(因为它就是这样)。不变性与值/引用类型无关。值类型可以是可变的,也可以是不可变的,引用类型可以是可变的,也可以是不可变的。不要忘记,如果您在发布后意识到另一个答案(更好或相同)已经发布,那么删除您的帖子就不需要花费任何成本,以避免问题与答案混杂在一起而没有添加任何内容。