+2  A: 

Is my understanding (if not my explanation) correct for the most part?

I do not agree in one point: A literal is some kind of compile time constant (as "Hello World", 5 or 'A'). However, there are no "Literal-Types"; the literal always is the actual value.

Primitive types are IMO "basic" types like string, int, double, float, short, ...

So primitive have their types of literals connected with them.

winSharp93
string isn't a primitive type. char is, though.
R. Bemrose
@R. Bemrose I was just going to say that. It is worth mentioning that string is a class System.String and that it resides on the heap as well.
JonH
I'm a little fuzzy on the "no literal types" comment. I think I understand what you're getting at, but isn't a string-literal "John Doe" imply that it is always a string? So some types support "literal notation" and literal notation *implies* type, but types themselves are not specifically 'literal'?
STW
@Yoooder what he means is there is no such thing as a literal type 'type' its just a literal period. Yes string name = "John Doe" is a string literal.
JonH
String lives in a weird nebulous world of being a primitive and a class I think. Mostly because if you create two different strings that are set to the same value, they will actually point to the same memory on the heap. See the string.IsInterned() function.
Nick
String isn't a primitive type. It *is* completely a reference type. Two different strings set to the same value will only refer to the same instance if you're using string literals or call Intern.
Jon Skeet
+1  A: 

I guess one thing you did not mention is space and allocation. Primitives are value types and are allocated on the stack (as long as they are not associated with an object) except for the string type as you mentioned (the string class allocates its space on the heap).

Although objects themselves contain primitives there storage resides where the actual object is allocated, which is on the heap.

Other then that your statement is pretty well written. Do you have a specific question that I missed :)?

JonH
So primitives are always value types; whereas literal values are just value notations that can apply to either value or reference types. Correct?
STW
well there are nullable types so dont forget those. int and System.Int32 are exactly the same, int is just an alias for System.Int32, they still give you the same result. In C#, if that is what you are after, classes and interfaces are reference types. Structs, enums are value types). All primitive types are value types but it doesn't go the other way.
JonH
@Yoooder what you said is correct, let me recommend a pretty good book on understanding this which got me to understand it pretty well. Skeet's C# in depth, specifically the beginning section around pages 45-55.
JonH
I'm sad to say that I have Skeet's book, and am well past those pages. (Hanging head in shame for not drinking in the knowledge imbued in the every word of the C# maestro) :(
STW
Well don't be so discouraged I've read that book several times and I can tell you I do not completly understand it all the time. I guess its definately worth keeping and referencing. The page you are after is 52. Take a good look at that, otherwise I think you understand the concept very well but you are looking too much into it. Take it as that is just how it is :-).
JonH
Thanks for the specific page. I've been trying to become a minor authority on some of these fundamental terms because we have a number of devs who are making wild assumptions based on inaccurate facts. "literal vs primitive" is a small point to argue, but it came up after some *very* incorrect statements about value and reference types--so I wanted to make sure I wasn't in-the-wrong on my understanding of them.
STW
Saying that "value types are allocated on the stack" is incorrect - it depends on the context. If the value is a member of a class, it will be on the heap for example. See P52 for more details... and Eric Lippert's great blog post: http://blogs.msdn.com/ericlippert/archive/2009/04/27/the-stack-is-an-implementation-detail.aspx
Jon Skeet
... and if it's any consolation to anyone, I don't completely understand the book all the time either, which is the fault of the writing rather than the reader :)
Jon Skeet
@jon I never said value types are on the stack. I said It may be worth noting that the above example x, and y are primitives by definition however they belong to the Point class which when created is stored on the heap. Primitives which are stored on the stack in this case are allocated in the same principle as their object, in this case they reside on the heap. You can see this at the top comments section.
JonH
@JonH: From your answer: "Primitives are value types and are allocated on the stack".
Jon Skeet
And from your comment: "Primitives which are stored on the stack in this case are allocated in the same principle as their object, in this case they reside on the heap." Any one particular value is either on the heap or on the stack - it can't be on both. The stack isn't the same as "the enclosing context's storage" which is sort of what I think you're trying to say.
Jon Skeet
@Jon but did you read the sentence right under it: Although objects themselves contain primitives there storage resides where the actual object is allocated, which is on the heap.
JonH
@Jon, I think you are misunderstanding me. Assume you have a class Person with some members int age, string name...etc. In this case even though int is a primitive when you do Person p = new Person(...); the entire object including the primitives are stored on the heap.
JonH
@JonH: Yes. Which means that your statement "Primitives are value types and are allocated on the stack" isn't correct in that situation, is it?
Jon Skeet
Well I guess if you are reading it and stopping and not going further then yes that is true. But what I meant was primitives that do not pertain to an object...
JonH
@Jon Skeet - I edited it in case someone happened to pause at that statement :).
JonH
@JonH: Then you should also consider captured variables. They end up being compiled into fields in an object, but in C# source code terms they're still local variables... the C# spec doesn't define how they're captured. What I'm really trying to get at is that the generalisation of "value type values live on the stack" isn't a useful one to start with. What *is* useful is to know that the value of a value type variable is the data itself, whereas the value of a reference type variable is a reference to an object, or null.
Jon Skeet
@Jon Skeet - I've heard it suggested that the *semantics* of working with value-types are more pertinent to consider than the *technicalities* (stack/heap, etc). Do you agree?
STW
@Yoooder: Absolutely. It's worth noting that the C# spec doesn't make any guarantees about the stack/heap. See Eric's blog post, linked above. The guy knows what he's talking about :)
Jon Skeet
@All, stack vs. heap is a silly debate when it comes to C#. In the days of C and C++ it mattered because it was possible to return pointers to the stack which then goes away and all other sorts of unfun things. In C#, stack vs. heap is abstracted away. If you run in to a problem because something is on the stack rather than the heap (or vice-versa) then (AFAIK) there is a bug in the compiler or the specification has a problem.
tster
@tster: your's is a valid point... I think the reason it so often comes up during the value/reference type talks is because so many people consider the stack/heap differences to be the main factor in considering value/ref types--then go on to make incorrect statements about the technicalities. At the end of the day I'm glad that Mr. Skeet agrees that ***semantics*** are the factor we should consider; unfortunately we're busy arguing *how* ref/val types work and not *why* to choose one over the other.
STW
@tster: Stack vs heap isn't *entirely* abstracted away. If you create a huge value type and have a recursive method with several (uncaptured) local variables of that type, you *will* run into a fatal StackOverflowException earlier than if you don't. It's definitely an implementation detail - but I don't think it's worth ignoring entirely either.
Jon Skeet
Any reason for the down vote?
JonH
@JonH: I'm wondering the same. Trying to review the answers I've received to figure out who best deserves the "accepted answer" point. Good discussions all-around, but I can't see any reason for a downvote.
STW
@Skeet, good point about the stack overflow. You would think I wouldn't have forgotten that considering the website I was posting on at the time ;)
tster
A: 

Don't forget there also exists the ASP.Net Literal class.

EDIT: Thus, an answer to the question in the title is no, as there isn't a "Primitive" class that provides the same functionality. This can be viewed as a bit of a smart alec response, though.

JB King
I think that Literal is different than the literal being discussed in this thread. The asp.net literal allows you to place words on a page like a label. We are referring to actual literals stored to say a string.
JonH
+1 for admitting to be a smart alec!
JonH
+2  A: 

Yes, a literal is a value expressed in source code - so while VB supports date/time and XML literals, C# doesn't.

From the C# spec, section 2.4.4:

A literal is a source code representation of a value.

As you say, this is unrelated to value type vs reference type - string is indeed a reference type.

One literal which no-one has mentioned yet it null by the way...

It's also unrelated to primitive types - from Type.IsPrimitive:

The primitive types are Boolean, Byte, SByte, Int16, UInt16, Int32, UInt32, Int64, UInt64, IntPtr, UIntPtr, Char, Double, and Single.

... the C# specification doesn't actually define the idea of a "primitive" type, but note that String isn't in the list above.

In terms of literals being compile-time constants... in C# every literal has a representation which can be baked directly into the assembly; the extra literals in VB mean they're not constants as the CLR would understand them - you can't have a const DateTime for example - but they're still literals.

Jon Skeet
JonH *did* mention nullables, so `null` has been covered to a degree :)
STW
One question of curiousity... assuming I have a custom Type which I *could* represent as a literal--is there a way of adding support for custom-literals in .NET/Visual Studio?
STW
@Yoooder: That would be a change to the C# compiler - and no, it's not supported. Possibly in C# 5, who knows? :)
Jon Skeet
@Jon - In my post above I did mention the nullable types.
JonH
@JonH: Nullable types, yes - but not the null literal. They're very different things.
Jon Skeet
Interesting - in CLR via C#, Richter includes string and object as primitives. I don't have the book on me now, but I believe he defines primitives as the types with special compiler support to use the "int i" kind of syntax rather than "Int32 i = new Int32()".
mbeckish
Int32 is the same as int, so that is quite strange. It's just an alias.
JonH
@mbeckish would you mind double-checking and verifying/expanding on that? Not sure I follow...
STW
btw, my interpretation from these discussions and some other reading is that primitives are perhaps described as the "elemental" data types whereas types composed of primitives may be described as "molecular" in that analogy. Perhaps not entirely accurate, but there doesn't seem to be a firm consensus on specifically what a primitive is
STW
@Yooder - here is a link to an article by Jeffrey richter that talks about this: http://msdn.microsoft.com/en-us/magazine/cc301569.aspx
mbeckish
A: 

I think that your understanding is mostly correct. As winSharp93 said, literals are values which themselves have types, but there's no such thing as a "literal type". That is, while you can have string literals, strings are not a "literal type". As you have guessed, what defines a literal is that the value is directly written down in source code, although your requirement that no type needs to be specified seems overly strict (e.g. F# has array literals, and can infer the type of the array literal [| 1; 2; 3 |], but cannot necessarily infer the type of the empty array literal [| |]).

Unfortunately, I don't think that there is a well-agreed-upon definition of what makes a primitive. Certainly, as Jon Skeet points out, the CLR has its own definition of primitiveness (Type.IsPrimitive), which rules out strings. However, other reputable sources consider string and even object to be primitive types within C#. I prefer this definition, since there is built-in support in C# for strings, such as the use of the + operator for concatenation and the use of == as value equality rather than reference equality, as well as the fact that the string type can be referred to using the short form string rather than having to use the full name System.String.

kvb
The use of == isn't "special" to string in particular - it's just an overloaded operator; you could write your own. + on the other hand *is* special (it uses String.Concat) and string literals are obviously special too. However, I don't see how they're really "primitive"... the fact is, the C# language specification doesn't give a definition of "primitive" so I don't think it's a good idea to pretend it does, if you see what I mean.
Jon Skeet
Just checking that article, it was written in the year 2000 - so the C# spec *may* have defined the term "primitive" back then, before it was really released. On the other hand, he repeats it in CLR via C# (P118). Given that it conflicts with the BCL definition, I don't think it's terribly helpful :(
Jon Skeet
@Jon Skeet: good point on `==` - I had forgotten that there was an `op_Equality` method on the string class. Although the C# spec doesn't provide an ironclad definition of what a "primitive" is, there are reasonably well-understood definitions which apply to multiple programming languages and can be used here (although there are certainly gray areas where we may not reach consensus).
kvb
@kvb: If there are grey areas, does it actually add any information? Especially given that the BCL has a very clear description which *doesn't* include object and string? In what way is a sequence of characters "primitive" in the first place?
Jon Skeet
A: 

Here is an MSDN page, talking about the CLS, that includes string as a primitive type:

The .NET Framework class library includes types that correspond to the primitive data types that compilers use. Of these types, the following are CLS-compliant: Byte, Int16, Int32, Int64, Single, Double, Boolean, Char, Decimal, IntPtr, and String. For more information about these types, see the table of types in .NET Framework Class Library Overview.

mbeckish
+6  A: 

I just wanted to inject a quick note here.

The C# language specification clearly defines "literal" -- a literal is a source code representation of a value. Literals are things like true, 10, 5.7, 'c', "hello" and null -- they are text that represents a specific value.

The C# language specification uses the word "primitive" twice; it is never defined and completely vague as to what it could possibly mean.

The C# language spec has no need to use or define the word "primitive" and therefore should not make use of this vague term. I've had a talk with Mads and we've agreed that future editions of the spec will be reworded to eliminate this usage completely.

How other type systems specifications -- the reflection library, the CLI, the VES, and so on -- define the word "primitive" is of course up to them.

Thanks for bringing up the question.

Eric Lippert