In C#, why is String a reference type that behaves

2019-09-15 02:58发布

A String is a reference type even though it has most of the characteristics of a value type such as being immutable and having == overloaded to compare the text rather than making sure they reference the same object.

Why isn't string just a value type then?

12条回答
唯我独甜
2楼-- · 2019-09-15 03:13

It is not a value type because performance (space and time!) would be terrible if it were a value type and its value had to be copied every time it were passed to and returned from methods, etc.

It has value semantics to keep the world sane. Can you imagine how difficult it would be to code if

string s = "hello";
string t = "hello";
bool b = (s == t);

set b to be false? Imagine how difficult coding just about any application would be.

查看更多
Melony?
3楼-- · 2019-09-15 03:15

The distinction between reference types and value types are basically a performance tradeoff in the design of the language. Reference types have some overhead on construction and destruction and garbage collection, because they are created on the heap. Value types on the other hand have overhead on method calls (if the data size is larger than a pointer), because the whole object is copied rather than just a pointer. Because strings can be (and typically are) much larger than the size of a pointer, they are designed as reference types. Also, as Servy pointed out, the size of a value type must be known at compile time, which is not always the case for strings.

The question of mutability is a separate issue. Both reference types and value types can be either mutable or immutable. Value types are typically immutable though, since the semantics for mutable value types can be confusing.

Reference types are generally mutable, but can be designed as immutable if it makes sense. Strings are defined as immutable because it makes certain optimizations possible. For example, if the same string literal occurs multiple times in the same program (which is quite common), the compiler can reuse the same object.

So why is "==" overloaded to compare strings by text? Because it is the most useful semantics. If two strings are equal by text, they may or may not be the same object reference due to the optimizations. So comparing references are pretty useless, while comparing text are almost always what you want.

Speaking more generally, Strings has what is termed value semantics. This is a more general concept than value types, which is a C# specific implementation detail. Value types have value semantics, but reference types may also have value semantics. When a type have value semantics, you can't really tell if the underlying implementation is a reference type or value type, so you can consider that an implementation detail.

查看更多
Emotional °昔
4楼-- · 2019-09-15 03:19

Also, the way strings are implemented (different for each platform) and when you start stitching them together. Like using a StringBuilder. It allocats a buffer for you to copy into, once you reach the end, it allocates even more memory for you, in the hopes that if you do a large concatenation performance won't be hindered.

Maybe Jon Skeet can help up out here?

查看更多
淡お忘
5楼-- · 2019-09-15 03:26

It is mainly a performance issue.

Having strings behave LIKE value type helps when writing code, but having it BE a value type would make a huge performance hit.

For an in-depth look, take a peek at a nice article on strings in the .net framework.

查看更多
时光不老,我们不散
6楼-- · 2019-09-15 03:28

Not only strings are immutable reference types. Multi-cast delegates too. That is why it is safe to write

protected void OnMyEventHandler()
{
     delegate handler = this.MyEventHandler;
     if (null != handler)
     {
        handler(this, new EventArgs());
     }
}

I suppose that strings are immutable because this is the most safe method to work with them and allocate memory. Why they are not Value types? Previous authors are right about stack size etc. I would also add that making strings a reference types allow to save on assembly size when you use the same constant string in the program. If you define

string s1 = "my string";
//some code here
string s2 = "my string";

Chances are that both instances of "my string" constant will be allocated in your assembly only once.

If you would like to manage strings like usual reference type, put the string inside a new StringBuilder(string s). Or use MemoryStreams.

If you are to create a library, where you expect a huge strings to be passed in your functions, either define a parameter as a StringBuilder or as a Stream.

查看更多
爷、活的狠高调
7楼-- · 2019-09-15 03:28

How can you tell string is a reference type? I'm not sure that it matters how it is implemented. Strings in C# are immutable precisely so that you don't have to worry about this issue.

查看更多
登录 后发表回答