Question

A discussion earlier today led me to question whether or not my understanding of primtives and literals is correct.


My understanding is that a literal type is specifically a type which can have a value assigned using a notation that both human and compiler can understand without specific type declarations:

var firstName = "John"; // "John" is literal

var firstName = (string)"John"; // *if* the compiler didn't understand that "John"
                                // was a literal representation of a string then I
                                // would have to direct it as such

My understanding of primitives is that they are essentially the elemental datatypes which the compiler can understand, such as int:

int age = 25;

...a literal could be non-primitive, such as VB9's support for XML literals. A non-real world example would be if System.Drawing.Point could be assigned with literals:

Point somePoint = 2,2; // both X and Y are primitive values, however Point is a
                       // composite value comprised of two primitive values

Finally (and this is the question that in turn led me to ask the above questions): My understanding is that whether a type is primitive or literal there is no direct relation to whether it is a Value or Reference type.

For example System.String is a reference type which supports literals. Custom-defined structures are composite value types which do not support literals.

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


Update: Thanks for the great info and conversations! To anyone finding this, make sure to read the comments as well as answers, there's some great clarifications spread around as well as a few interesting side-notes.

btw: it's a toss-up between which answer really is deserving to get the big green check. I'm giving it to the unfortunately downvoted answer which contains not only a decent answer but lots of clarification and info in the comments thread. To be fair there isn't one best answer here, there's at least three :)

Was it helpful?

Solution

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 :)?

OTHER TIPS

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.

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.

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.

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.

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.

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.

Just to add that there is another type that blurs the limit: System.Decimal whose values can be expressed as literals in the C# language, but which is not a .Net primitive type.

IMHO primitive types could be simply defined as types that directly "exists" in every underlying platform/host: if you've already played with assembly language you know that you have bytes, words, double-words... but you have no strings or decimals.

Indeed .Net decimals are "emulated" by the .Net runtime and are not directly handled by the hardware which only understands IEEE 754 floating point numbers (float and doubles which are then primitive types).

By extension of the notion of literal values "Literal types" could be considered as any type whose values can be directly expressed in a given language (C#, VB.Net, CIL...). With this definition literal types would be: all the primitive types + strings + decimals.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top