views:

409

answers:

5

Hello everyone,

A few days ago, I decided to start learning C#. So, I got a book and started reading and practicing with code. I was surprised when I saw that string in C# is considered a primitive type.

But I was more surprised when I saw that string, as well as all the other primitive types in C# have operations. I'm a Java developer and my understanding was that primitive data types don't have operations, only classes have. But in C#, the following is valid:

string name = "alex";
Console.WriteLine(name.ToUpper());

How is this possible? Are they really primitives? What am I missing here?

+1  A: 

They are aliased to their matching System Namespace types in .Net. Here's a rundown of the alias list for value types in .Net:

Nick Craver
There's no boxing/unboxing with string, it is a reference type.
Bruno Reis
@Bruno Reis: Thanks for the catch, I often forget this, added a full reference of ones that do box/unbox in case it's helpful to someone later.
Nick Craver
Still wrong: **boxing** is treating a value type as `Object`. As mentioned, **Int32 is the same as int**. If you "cast" an `int` to an `Int32`, there's absolutely no boxing taking place. Boxing is converting to object. Your list describes the type aliases, but it has absolutely nothing to do with boxing/unboxing. You should review these concepts.
Bruno Reis
FYI, any value type is subject to boxing/unboxing, even the "custom" ones you may define yourself. What you describe is a concept completely unrelated to boxing/unboxing.
Bruno Reis
@Bruno Reis: Thanks!, I had always though it unboxed on a (Int32)int scenario sticking it on the stack for method calls, I see with our generated IL that it doesn't...learn something every day on here. I updated this in case someone else trips over it later. I appreciate the lesson, I'm sure it'll help in project down the road.
Nick Craver
+11  A: 

string, in C#, is a class - it's an alias for System.String.

However, all types in .NET have methods. It is truly object oriented, and everything derives from System.Object, which also means that the methods of System.Object work on every type in C#.

Reed Copsey
How about structs (as `int` aka `Int32` and other value types are structs)? From my understanding they don't support inheritance. Are they still derived from `System.Object`?
0xA3
@divo: All `struct` derive from `System.ValueType` which derives from `System.Object` and they are implicitly `sealed` (meaning they can not be derived from).
Jason
Aliasing and Inheritance for posterity: C# string = System.String (class) > System.Object | C# int = System.Int32 (struct) > System.ValueType > System.Object | It always ends at System.Object. See System.Object methods here http://msdn.microsoft.com/en-us/library/system.object_members.aspx and see these on any instance or value in your application.
John K
Be careful! Not everything derives from `System.Object`!
Jason
@Jason: Thanks for the clarification! What does *not* derive from `System.Object` then?
0xA3
@divo: Pointer types and interfaces for example.
Jason
@Jason: Good point!
Reed Copsey
+3  A: 

Short answer is that they're not really primitives. The compiler will switch out your string with a String object.

Alconja
`string` is just a keyword that is an alias for `System.String`.
Jason
@Jason - Isn't that all an alias is? Something that is effectively a place-holder name for some other *real* thing? In other words isn't what you're saying logically the same as saying the compiler switches `string` to `System.String`? Now I'm not sure if it happens when compiling to CIL or when the CIL is JIT'd at runtime, but at some point a `string` **is** a `System.String` right?
Alconja
@Alconja: I guess I just misunderstood what you meant by "the compiler with switch out your `string` with a `String` object." I thought you were saying that the two are different types and the compiler is just using `String` when you say `string` but I realize now (based on your comment) that is not what you meant. My apologies; your understanding is correct. It happens at compile time; that is replacing all instances of `string` with `String` in your code or vice versa will emit exactly the same IL.
Jason
+3  A: 

Since C# represents all primitive data types as objects, it is possible to call an object method on a primitive data type. (Source: MSDN - Data Types - C# vs Java)

Daniel Vassallo
+15  A: 

string is not a primitive type in C#. It's one of two predefined (i.e., part of the language specification) reference types in C# (the other being object). The primitive types in C# are Boolean (bool), Byte (byte), SByte (sbyte), Int16 (short), UInt16, Int32 (int), UInt32 (uint), Int64 (long), UInt64 (ulong), IntPtr, UIntPtr, Char (char), Double (double), and Single (single). Note that the specification states "it is also possible to use structs and operator overloading to implement new “primitive” types in the C# language" but that typeof(MyStruct).IsPrimitive is false if MyStruct is a user-defined struct.

I got a book and started reading and practicing with code. I was surprised when I saw that string in C# is considered a primitive type.

The book said this? Which book?

I'm a Java developer and my understanding was that primitive data types don't have operations, only classes have.

Plainly and simply, C# and Java are different languages. In C# there is the notion of object from which almost everything derives (yes, there are exceptions the most important of which is interfaces). From object there is a derived type called ValueType. Derivatives of ValueType are structs which have value semantics. All other derivatives of object are reference types. All of these objects encapsulate data and behavior (i.e., they can have methods).

string name = "alex";

Console.WriteLine(name.ToUpper());

How is this possible?

I don't understand your confusion with this code snippet. name is an instance of string that is definitely assigned by the string literal "alex" and we are invoking one of the overloads of the method String.ToUpper on name. Then the overload of Console.WriteLine that accepts an instance of string is invoked. You can even do this

Console.WriteLine("alex".ToUpper());

Are they really primitives?

No. string is not a primitive.

What am I missing here?

That C# and Java are related but very different programming languages.

Jason
You're right, after a little research (and reading all your answers here) I found out that there aren't any primitives in C#. I wasn't confused with the code, I was only confused that you're allowed to perform operations in types like int. For example, int i = 5; i.ToString();
Alex
`ToString` is a `virtual` method defined on the class `object` from which `ValueType` derives from which `Int32` derives (`int` is a reserved keyword in C# that is short for `Int32`). `Int32` provides an `override` of `ToString`.
Jason
+1 Very nice answer. (By the way, here is a quick verification of your assertion that `String` isn't a primitive type: `typeof(String).IsPrimitive`)
Andrew Hare