To String or to string

csharp style code 115 comments suggest edit

Like many developers, I have many strong opinions about things that really do not matter. Even worse, I have the vanity to believe other developers want to read about it.

For example, a recent pull request changed all instances of String to string. As a reminder, String actually represents the type System.String and string is the nice C# alias for System.String. To the compiler, these are the exact same thing. So ultimately, it doesn’t really matter.

However, as I just said, I care. I care about things that don’t matter.

Resharper, a tool we use to maintain our code conventions, by default suggests changing all String to string. But this doesn’t fit the convention we follow.

To understand the convention I have in my head, it probably helps to think about why are there aliases in the first place for these types.

I’m not really sure, but types like string and int feel special to me. They feel like primitives. In C#, keywords are lowercase. So in my mind, when we’re using these types in this manner, they should be lowercase. Thus my convention is to lowercase string and int any time we’re using them in a manner where they feel like a keyword.

For example,

int x;
string foo;
string SomeMethod();
void AnotherMethod(string x);
public string Foo { get; }

But when we’re using it to call static methods or calling constructors on these types, I want it to look like a normal type. These constructs don’t look like you’re using a keyword.

var foo = String.Empty;
String.Format("blah{0}", "blah");
var baz = new String();

Maybe I’m being too nitpicky about this. For those of you who also care about unimportant things, I’m curious to hear what your thoughts on this matter. Is it possible to configure R# or other tools to enforce this convention?


One of the reasons I follow this convention is for readability. When things don’t fit my expectations a tiny bit of extra processing is needed. So as I’m scanning code in Visual Studio and I see keyword.MethodCall it takes a second.

Having said that, a commenter noted that the corefx coding guidelines always use lowercase. And one of my principles with coding conventions is I tend to adopt something I feel is something of a widespread standard even if I disagree with it because at the end of the day, these are all mostly arbitrary and rather than spend a lot of time arguing, I’d rather just point to something and say “We’re doing it that way because why not?” That’s why I tend to follow the Framework Design Guidelines for example.

Having said that, I still need to let this one sink in.

Found a typo or error? Suggest an edit! If accepted, your contribution is listed automatically here.



115 responses

  1. Avatar for Blake Niemyjski
    Blake Niemyjski December 16th, 2015

    I 100% agree and this is the convention for all of our projects as well.

  2. Avatar for Matthew Jones
    Matthew Jones December 16th, 2015

    I'm totally with you on this convention. Now, though, I've noticed VS 2015 prompting me to convert String.Method calls to string.Method, which messes with my internal conventions. Also interested to hear how to configure VS to stop doing this.

  3. Avatar for Stefan Kip
    Stefan Kip December 16th, 2015

    I always use the lowercase variant everywhere, sorry.

  4. Avatar for Phillip Haydon
    Phillip Haydon December 16th, 2015

    Only use lowercase. Never the uppercase version.

  5. Avatar for Bryan Livingston
    Bryan Livingston December 16th, 2015

    Use string when you're using it as a value type. Use String when you're using it as a class.

  6. Avatar for Diego Mijelshon
    Diego Mijelshon December 16th, 2015

    I use lowercase because I'm lazy. Shift is one more key to press. Ugh.

  7. Avatar for Petr Krebs
    Petr Krebs December 16th, 2015

    One thing I'd ask myself is whether the convention actually adds any value. Does it improve readibility? Does it allow you to express an intent that would otherwise be lost or not clear? Does it help anyone in any way? In this particular case, no, no and no. So, keywords only all the way for me :-)

  8. Avatar for John Kraft
    John Kraft December 16th, 2015

    I don't like capitals or underscores; they make my hands hurts. It's a burden of being old and having short fingers. This is why I always use the aliases.

  9. Avatar for tvanfosson
    tvanfosson December 16th, 2015

    I only use the aliases because it's possible to define your own String class in a different namespace. That would be stupid, yes, but I've seen a lot of stupid things done. It's not a good reason, but it is a valid reason to stick with the aliases.

  10. Avatar for sonofpirate
    sonofpirate December 16th, 2015

    I prefer to use the .NET Types, not the old C-style syntactic sugar, because I like to have all of my types highlighted the same color in the IDE. As Phil said, "int" and "string" appear as keywords. I want my keywords to appear as keywords and my types to appear as types.

  11. Avatar for Alan Parr
    Alan Parr December 16th, 2015

    Completely agree with @haacked,I rage a little when I see it used the other way

  12. Avatar for Dave Glick
    Dave Glick December 16th, 2015

    This is exactly what I prefer as well.

  13. Avatar for wqweto
    wqweto December 16th, 2015

    Rule 11 explains VS defaults or vice versa.

  14. Avatar for Craig Wagner
    Craig Wagner December 16th, 2015

    Another vote on the agree side, for exactly the same justification as yours.

  15. Avatar for haacked
    haacked December 16th, 2015

    I actually think it does help readibility. I find that I unconsciously get stuck at things that don't look right to me. So `keyword.MethodCall` causes a tiny bit of extra processing in my brain. Your mileage may vary.

  16. Avatar for Miguel Lira
    Miguel Lira December 16th, 2015

    This may have simply fallen through some check but the corefx repo violates #11:

    I've always held the same view expressed by @haacked:disqus but lately have avoided fighting the defaults.

  17. Avatar for Ryan Hoffman
    Ryan Hoffman December 16th, 2015

    100% agree and ditto for our organization.

  18. Avatar for eatfrog2
    eatfrog2 December 16th, 2015

    100% agree

  19. Avatar for Mark Avenius
    Mark Avenius December 16th, 2015

    Just as food for thought, some keywords do have members. 'base' and 'this' come to mind (I know what you're thinking, "don't use them." But sometimes they are necessary: case in point, in an overridden method MyMethod, you may need to call base.MyMethod().)

    Not saying that I disagree per se, but some of the argument doesn't quite hold water.

    By the way, I happen to always use keywords, which throws me off when dealing with Sql types of Int32 and the like ☺

  20. Avatar for Brad Westness
    Brad Westness December 16th, 2015

    I actually think the SQL thing is a feature, because then it's extra explicit when you're doing interop between C# "primitives" and some other interop type (even if it's int vs. Int32 or whatever).

  21. Avatar for Caio Proiete
    Caio Proiete December 16th, 2015

    "types like string and int feel special to me. They feel like primitives" - I stopped thinking like that because of `DateTime` - which should be `datetime` to follow these "rules"

  22. Avatar for Brad Westness
    Brad Westness December 16th, 2015

    A DateTime has properties on it (like .Year, .Month, etc), which makes it more conceptually a complex type rather than a primitive IMHO.

    The "primitive" types feel appropriate to me for things that can be initialized with a literal, e.g. int foo = 12 or string bar = "baz".

  23. Avatar for Caio Proiete
    Caio Proiete December 16th, 2015

    Really? Not sure I agree with that. String has properties too, has more public methods than DateTime (String = 132 vs DateTime = 93) and String implementation has almost twice as much code as DateTime - I think String is clearly more complex than DateTime if looking at API surface or implementation

  24. Avatar for Brad Westness
    Brad Westness December 16th, 2015

    The only properties on String are the underlying char array and the length. DateTime is way more complicated, you're just not counting all the other types that DateTime depends on for handling timezones, calendar systems, etc.

    I agree that string is kind of pushing the boundary of what can be thought of as a "primitive" because it is, in effect, an array of chars. However, a DateTime still has way more component parts to it than does a string.

  25. Avatar for Fredrik
    Fredrik December 16th, 2015

    To add to the int camp, I used the C# language specification to come to my preference,

    "Each of the predefined types is shorthand for a system-provided type. For example, the keyword int refers to the struct System.Int32. As a matter of style, use of the keyword is favored over use of the complete system type name."

  26. Avatar for Gammidgy
    Gammidgy December 16th, 2015

    You're bang on the money with this one, Phil. Those who disagree with you also squeeze the toothpaste from the middle and are mean to animals.

  27. Avatar for jenyayel
    jenyayel December 16th, 2015

    I use the same convention.

  28. Avatar for Caio Proiete
    Caio Proiete December 16th, 2015

    Alright. Fair point on DateTime dependencies - it may end up being more complex after all (didn't measure but I can see it would be possible). Still, I don't think is a valid argument for not having a `datetime` alias... All other structs do, String is a class... And yet it deserves an alias? Not buying.

  29. Avatar for CarlMess
    CarlMess December 16th, 2015

    I agree, I also tend to look into the productivity side, less capitals: faster typing for larger projects...

  30. Avatar for Stuart
    Stuart December 16th, 2015

    I absolutely agree with this, this is my preference too

  31. Avatar for Brett Jacobson
    Brett Jacobson December 16th, 2015

    +1 in agreement with Phil about using String. But I also hate using ! because its so hard to notice on high res monitors, and I also put == true on my conditionals.

  32. Avatar for Ken Egozi
    Ken Egozi December 16th, 2015

    String is for VB.NET !!!!!

    (trolling #1)

  33. Avatar for Ken Egozi
    Ken Egozi December 16th, 2015

    can't you just go fmt the thing?

    (trolling #2)

  34. Avatar for Ken Egozi
    Ken Egozi December 16th, 2015

    True story: this reminds me of an interviewee a good while back, that when asked about "is string a reference or value type" said that it is a value type, because it is in dark blue, just like int and bool

    (not trolling, and not kidding)

  35. Avatar for Ken Egozi
    Ken Egozi December 16th, 2015

    The bloke was also sure that DateTime is a reference type. It is light blue after all

  36. Avatar for Mark Avenius
    Mark Avenius December 16th, 2015

    I completely agree, and I think it is a good thing because it makes it obvious if you are going to lose precision (hopefully.)

  37. Avatar for Matti Petrelius
    Matti Petrelius December 16th, 2015

    I always use the lower case string and int for consistency. Whether I am calling a static method or specifying a type. It makes it more clear that were dealing with the same types. Especially with int and Int32 it might not always be clear that they are the same thing. I think it is easier to read code with only string and int instead of both capitalized and lowercase version in various places. Once you get over the fact that even types that seem primitive can have methods there really is no reason to have two different ways of using string.

  38. Avatar for Teacher
    Teacher December 16th, 2015

    ...and I thought I was the only "wicked" one ;)

  39. Avatar for Philippe Vlérick
    Philippe Vlérick December 16th, 2015

    Use System.String as a value type? It's a reference type :-)

  40. Avatar for Sotirios Mantziaris
    Sotirios Mantziaris December 17th, 2015

    i could agree on String, but if we have a mix of int and Int32.Parse, Int32.MinValue in code, this i don't like. Obviously i would not write my int as Int32 in code to keep parity! Plus you have to add a using statement of System to your code. So for me it is string.Empty and int.MaxValue. My 2 cents

  41. Avatar for Helena Cayton
    Helena Cayton December 17th, 2015

    Absolutely agree. string.Format just looks like Java, and I can really do without that in my codebase!

  42. Avatar for banerjeeindranil16
    banerjeeindranil16 December 17th, 2015

    it's the fight before christmas. lowercase all the time, every time! :-)

  43. Avatar for Luka Ranisavljevic
    Luka Ranisavljevic December 17th, 2015

    For me it's the opposite that helps readability. I guess it's the same reasoning as yours, just that for me String.Format() causes that extra bit of processing in my head. I suppose it's a matter of what you are used to and what you expect when reading code.

  44. Avatar for Chris
    Chris December 17th, 2015

    "String" forces you to include "using System;" at the top
    "string" helps you reduce namespace bloat (albeit a little)

  45. Avatar for Joseph N. Musser II
    Joseph N. Musser II December 17th, 2015

    Same here. `String.Format` or `String.Empty` looks confusing and a tiny bit disgusting; but so does using `Int16.MaxValue` instead of `short.MaxValue`. It feels more idiomatic to use the C# keyword.

  46. Avatar for Sotirios Mantziaris
    Sotirios Mantziaris December 17th, 2015

    already stated this in my comment! ;)

  47. Avatar for Sotirios Mantziaris
    Sotirios Mantziaris December 17th, 2015

    i would have said imaginary type (like the complex numbers)! would i have passes the interview? ;) (troll)

  48. Avatar for CodingGorilla
    CodingGorilla December 17th, 2015

    Also agreed, regarding Phil's update, I suggest we get someone to change the coding guidelines - our way is right! :)

  49. Avatar for Sotirios Mantziaris
    Sotirios Mantziaris December 17th, 2015

    string and System.String are the same. the former is just an alias to the latter.
    string or String is always reference type!!!

  50. Avatar for Joshua Drake
    Joshua Drake December 17th, 2015

    Another vote for String.METHOD_CALL and string type declaration. I note that MSDN follows suit:

    public static String Test(string s)
    if (String.IsNullOrEmpty(s))
    return "is null or empty";
    return String.Format("(\"{0}\") is neither null nor empty", s);

  51. Avatar for dotnetchris
    dotnetchris December 17th, 2015

    string is a reference type that masquerades as a value type

  52. Avatar for Chris Nielsen
    Chris Nielsen December 17th, 2015

    Yes, yes, and yes again! I've been mandating or pushing for this exact same convention at every job I've worked at since. NET came out (~15 years). Lowercase int is a primitive type, use it as such. Int32 is a class, use it as such. Method calls on a lowercase word that has syntax highlighting make me stop reading the code and switch into analysis mode to see how far the Java/Javascript syntax "infestation" has spread. I hate it.

  53. Avatar for Caio Proiete
    Caio Proiete December 17th, 2015

    What about DateTime? :)

  54. Avatar for Ignacio Calvo
    Ignacio Calvo December 17th, 2015

    I think that Phil has really more problem with calling static methods (such as Empty and Format) on a thing that doesn't look like a class because it's lower case. 'this' and 'base' represent an instance, not a class, so they look nice being lower case.

  55. Avatar for Mark Avenius
    Mark Avenius December 17th, 2015

    Right, but he also specifically called out that part of the preference is due to string and int being keywords. this and base are also keywords.

    I see what you mean, but I was just pointing out a slight inconsistency in that line of thinking.

  56. Avatar for Gabriel Garcia
    Gabriel Garcia December 17th, 2015

    I always go for the uppercase names. Yes, always. Why? Types are PascalCase in .NET. Period. Why have silly exceptions?

  57. Avatar for Gabriel Garcia
    Gabriel Garcia December 17th, 2015


  58. Avatar for Jason.W He
    Jason.W He December 17th, 2015

    Non official Guideline have opposite one compare to corefx.

    AV2201 Use C# type aliases instead of the types from the System namespace 
    For instance, use object instead of Object, string instead of String, and int instead of Int32. These aliases have
    been introduced to make the primitive types a first class citizen of the C# language so use them accordingly,
    Exception When referring to static members of those types, it is custom to use the full CLS name, e.g.
    Int32.Parse() instead of int.Parse().

  59. Avatar for Chris Nielsen
    Chris Nielsen December 17th, 2015

    DateTime never shows up in the separate color that int and string do. It is always the same color as full class types, like Int32 and String do.

    The main issue I have is that we're ingrained with the knowledge of the difference between value and reference types. So even though int and Int32 are synonymous, using Int32 as a *type* shows it in the wrong color, so unless you're paying attention, then readability-wise it will read as a reference type.

    It really boils down to the colors chosen for syntax highlighting. Using Int32 as a *type* shows it in the wrong color (and casing) to easily read over it and recognize a value type without having to stop and think about it. And using int.Parse() shows it in the wrong color (and casing) to read over it and recognize a class being invoked without having to stop and think about it.

    Those slight mental pauses (which Phil mentions) are one of the main "code smells" I watch for when reading code. If I have to stop and process some code instead of reading it, then I look for why and how I might fix it.

  60. Avatar for Chris Nielsen
    Chris Nielsen December 17th, 2015

    I agree, it helps with readability in a significant way for me. As I said in a comment above, every time I have to stop and process the code, instead of just reading it, those little pauses add up, just as you say. And it isn't so much that I've simply gotten used to it. I've worked at jobs where they mandated a style contrary to my preference, and I've gotten used to it, and those pauses to process have gotten smaller. But as soon as I have the choice, I revert to lowercase type usage, and uppercase class usage, simply because for me it just makes sense.

  61. Avatar for Chris Nielsen
    Chris Nielsen December 17th, 2015

    Another point to make, for those of us that prefer "string myValue = String.Empty;" ... I think I'm safe in saying that if C# had a lowercase synonym for DateTime, we would likely use it the same way. e.g. "datetime myValue = DateTime.Now;". That does look like it's begging for camel casing though, and dateTime as a type/keyword would just look weird. DateTime is also not one of those types that is semi-universal and is drummed into your head that it's a value type.

  62. Avatar for Chris Rogers
    Chris Rogers December 17th, 2015

    Sorry - cannot agree with you. I prefer consistency over "mixing it up". Lowercase everywhere for me. Uppercase feels a little jarring.

    Have always found it interesting how we developers will point to coding guidelines to support our position when we agree, but disregard them and call them "wrong" when we don't.

    Next, can we talk about brace positioning? Or implicitly typed local variables? :-)

  63. Avatar for Chris Nielsen
    Chris Nielsen December 17th, 2015

    The only impact that using directives have is that the compiler knows which code to link, when it finds usages of code in that namespace, which then at runtime causes the appropriate assemblies to be loaded. I can guarantee you that your program is already loading the core assemblies where the System namespace lives (mscorlib), even if you clean all the using System directives out of every file in your project/solution. There is zero overhead to having unused using directives, because the compiler optimizes them out. But unless you're lucky enough to have ReSharper or a similar tool, working in a file that someone was fastidious enough to remove all unused usings, you're going to have a little hiccup when you go to use something that's pretty standard in the language (e.g. Console, LINQ, etc.) when you have to remember to go back and put that using directive back.

    I personally take the default class template's list of 5 using directives, and make sure that every file in my solutions have those five, even if they're not used. ReSharper clearly grays them out for me, and a lot of times automatically removes them, but I always put them back.

    Back in my more junior days I had too many times when I went to type a LINQ extension method and it wasn't in Intellisense and showed a red squiggly compiler error. And I had to sit there for a few minutes figuring out what the heck was wrong, simply because we removed the using directive to keep our files "clean".

    Nowadays, it's second nature, and with ReSharper it's even less so. But I want to help my junior devs have that little bit less of friction as they're coding.

  64. Avatar for Chris Rogers
    Chris Rogers December 17th, 2015

    To me, upper case String looks like VB! I can do without that too! ;-)

  65. Avatar for Chris Nielsen
    Chris Nielsen December 17th, 2015

    It isn't hard to understand why we use coding guidelines as an Appeal To Authority, because without it then it's just an argument of opinion. Religious debates go nowhere. Debates with something to refer to as more authoritative are more substantive as you have someone who ostensibly "knows better".

    The flip side to that coin is that really it all comes down to preference to a large degree, and I doubt any of us will find a coding standard that we completely agree with. It's about readability, which is different for different people. But there *are* some baselines. You don't open any published book and see inconsistent paragraph spacing. Same with "good" code, it's consistent and follows the logical baselines that nearly everyone can agree on as qualifying as clean code.

    The third side of that two-sided coin is that whenever referring to Microsoft documentation for coding/naming guidelines, you have to understand that MS is a big company with lots of teams and lots of egos, and they don't even have a single coding standard that everyone in the company follows. The P&P team (or whoever) can release all the recommendations they want, but you're still going to find code in MS products that doesn't follow those conventions.

  66. Avatar for Chris Rogers
    Chris Rogers December 17th, 2015

    Well .... yes - you've expanded on the very dichotomy which i alluded to.

    If personal preference is important, and we're quite happy to reject external guidelines when they don't suit us, then we inherently lose any moral right to "Appeal To Authority" when it does happen to suit us.

  67. Avatar for Eric Richards
    Eric Richards December 17th, 2015

    I sorta wish that DateTime was a reference type, instead of a value type. Then I wouldn't have to fool around with Nullable<datetime>'s as much when I want to represent something that might have a date, or might have not date. Particularly when those things go into databases, where the range of the .Net DateTime doesn't match up with the T-SQL datetime.

  68. Avatar for Chris Nielsen
    Chris Nielsen December 17th, 2015

    No, it isn't that simple. We don't lose any moral right, we are simply using something to back us up if we want a particular point codified into our personal (team's) coding standard. Because chances are, the points in that particular standard that we don't agree with or don't want to implement, we can find a different standard that puts it in the form we do prefer.

    The important point being that you have a coding standard for your team, and you try to use conventions that are common, if not prolific, across the industry (rather than picking one particular standard and considering that one, and none other, "holy writ", even if there are parts you don't like).

    Plus you missed where I said there *is* a common baseline that pretty much everybody can agree upon. C# coding styles have some very prolific tenets that pretty much every team follows (e.g. Pascal-cased methods, vs Java/Javascript's camel-casing).

  69. Avatar for Ian Yates
    Ian Yates December 17th, 2015

    I completely agree. I've never even thought of doing string.isNullOrEmpty() - it just feels wrong. It shouldn't matter but IMHO it does :D
    I also tend to have a stringExtensions.cs which turns many of these calls into " extension methods anyway so I don't run into it too much in practice.

    There are always fun exceptions though. I'd do Dictionary<string, string=""> rather than Dictionary<string, string=""> I *think*. Return types from a method are always string, not String. Same goes for parameters.

  70. Avatar for Chris Rogers
    Chris Rogers December 17th, 2015

    Recall that the question driving this particular discussion is centered around something which the author himself described as unimportant and which doesn't matter. So no - on such things, there really are NO baselines.

    In fact, I think you'd be surprised at how varied different conventions can be - including matters of more substance.

    On any particular issue, if a team containing differing view points are each looking around for something to "back them up" in their stance, they will each find what they're after. So we're deceiving ourselves if we think we're doing anything other than just making up whatever we feel works for us. And there's nothing wrong with that at all. Do what works for you and your team!

    I have never said that we should follow any "holy writ".

    Simply be aware that looking around for justifications to back up your existing preferences - and ignoring them when you don't agree is something called "Confirmation Bias".

  71. Avatar for Manoj Kulkarni
    Manoj Kulkarni December 17th, 2015

    I am also using the same convention

  72. Avatar for Emmett E. Childress Jr.
    Emmett E. Childress Jr. December 18th, 2015

    Great post! I have been trying to convince myself that R# is right for the last 3 years. The method calls on the aliases always stops me in my tracks. I'll go ahead and take the plunge.

  73. Avatar for Adam Rodger
    Adam Rodger December 18th, 2015

    The problem is that your rule could actually see them used interchangeably on the same line, so to me this actually adds that 'bit of extra processing':

    float x = Single.NaN;

    It's not too bad with string/String or int/Int32, but float/Single just looks really odd.

    Whereas if the rule is "always use the keyword style" you can't really get that wrong. Remember it's all about making it easy to do the right thing and more difficult to do the wrong thing.

  74. Avatar for James Curran
    James Curran December 18th, 2015

    I generally follow your pattern of "string" vs "String" for pretty much the same reasons.

    However, it should be noted that using "String" will fail unless you have "#using System;" "string" does not have that requirement. (Granted one very rarely writes C# code with #using System, but it technically not required)

  75. Avatar for SharpTag
    SharpTag December 18th, 2015

    There is probably a higher percentage of people with OCD in the prgramming profession. Which might explain why these discusions get any kind of traction in 2015 when plenty of tools exist to re-format code in a deep manner so that absolutely no guidelines should be wasted on any code appearance that can be auto-formatted.

    With Roslyn, most of these "syntactic dictator" guidlines can be eliminated to enable people to concentrate their coginitive resources in a more useful manner.

  76. Avatar for Chris S.
    Chris S. December 21st, 2015

    R#er is responsible for a far worst crime: turning every type declaration in to a var, even ints. After some discussion we've settled on only using vars when the right side type makes it obvious (e.g not on method calls) and not for inbuilt types.

    I definitely don't think it's picky as you spend 90% of your time reading code (to paraphrase Uncle Bob) so removing patterns you're not familiar with is important.

  77. Avatar for Oisín G.
    Oisín G. December 22nd, 2015

    Yep, I do the same thing.

  78. Avatar for Oisín G.
    Oisín G. December 22nd, 2015

    I feel the exact opposite, therefore you suck and you should burn in visual basic hell.

  79. Avatar for Andy c
    Andy c December 22nd, 2015

    keywords only means no "using System;" needed just to use string, int, etc.

    one less line of code = winning.

  80. Avatar for abatishchev
    abatishchev December 23rd, 2015

    Unfortunately Resharper stil can't be configured to follow this convention: it easier suggest to upper-case `string foo` or lower-case `String.Format`. The same for using `this.` only for instance properties. Everything or nothing. And this is end late 2015!

  81. Avatar for JaredPar
    JaredPar December 28th, 2015

    > To the compiler, these are the exact same thing. So ultimately, it doesn't really matter.

    Usually ...

    The type String is actually not special cased by the compiler in any way. It is just a type with a name that goes through the normal type name lookup rules. Hence it can bind to types that are not System.String or even System.String in a different assembly.

    The type string though is special cased by the compiler. It will be the type System.String in the assembly deemed to be the core library (mscorlib, System.Runtime).

    This means it's possible for String and string to be different types. For example:

    This is actually why I prefer string over String: it's unambiguous. Code which uses string will bind to the type I expect no matter what context it is used in. String though is subject to interpretation.

  82. Avatar for Joseph N. Musser II
    Joseph N. Musser II December 30th, 2015

    Lol, don't overdo it with the intelligent replies man ;-)

  83. Avatar for James Kind
    James Kind December 30th, 2015

    Completely agree with you on this Phil!

  84. Avatar for Oisín G.
    Oisín G. December 30th, 2015


  85. Avatar for Lucas Byers
    Lucas Byers January 1st, 2016

    I also expect a convention but the exact opposite of yours. I expect to see string and int and it is more readable to me that way. If people use String or Int32 it takes me some additional processing and reading time.

  86. Avatar for Gabriel Garcia
    Gabriel Garcia January 14th, 2016
  87. Avatar for Gabriel Garcia
    Gabriel Garcia January 14th, 2016

    All of your type declarations besides int, string, etc. are ambiguous, then. So this makes proper typing an impossible task for you. That is unfortunate.

  88. Avatar for Gabriel Garcia
    Gabriel Garcia January 14th, 2016

    Interesting. IDEs could have a user-configurable "code lens" with code transformations (which apply on-the-fly) that suit the user's OCD needs, while the actual code text file follows whatever their team's conventions are.

  89. Avatar for Gabriel Garcia
    Gabriel Garcia January 14th, 2016

    VS's C# "new file" template includes `using System;` was well as many other using statements.

  90. Avatar for JaredPar
    JaredPar January 14th, 2016

    Ambiguity implies that what name a type binds to is undefined. That is not the case here. The name binding occurs according to the language spec rules. The only issue here is that String simply obeys those rules vs. being a predefined type.

  91. Avatar for Gabriel Garcia
    Gabriel Garcia January 14th, 2016

    Then there is no ambiguity. I'm glad to hear that.

  92. Avatar for Christopher Haws
    Christopher Haws May 15th, 2016

    I personally use the system type rather than the alias everywhere. I personally think there is an issue with code like "public int GetInt32()". This could become a problem if someday in the future, int switches from being a 32-bit integer to being a 64-bit integer. We saw this happen in C++ in the past. System types are declarative, whereas the aliases can be obscure (short = Int16, float = Single, long = Int64, etc.).

    This especially comes in to play when P/Invoke'ing. In C and C++, an int is defined as "Type int is an integral type that is larger than or equal to the size of type short int, and shorter than or equal to the size of type long." They don't specify the size because it can change depending on how you compile the library. If you tried to p/invoke a method that is using an int in C++ using the alias int in C#, you could run into issues with overflow in unmanaged code. Using the system types, you are always declaring the size.

  93. Avatar for Nyerguds
    Nyerguds June 28th, 2016

    Personally I prefer using the class notations. Why? Well, first of all, because "int" and "long" and "short" and the lot are notorious for changing in meaning between languages. No thanks. I'll just write "Int32" every time, so it will never get it confused with Int16 or Int64, even if the code is opened in 20 years and everyone's definition of "int" is Int128 :p

    And if I do it with that, why bother using any of these primitive types at all? They all have functions on them, so internally they're all classes anyway. I prefer using them as what they really are. Remove the ridiculous legacy-baggage duality by simply not using the primitive types.

  94. Avatar for Nyerguds
    Nyerguds June 28th, 2016

    Nope. It's an immutable type. It has nothing to do with the string-String duality; DateTime is the same and has no "primitive type".

  95. Avatar for Nyerguds
    Nyerguds June 28th, 2016

    That would imply you define it as "String myStr" if you're planning to later call myStr.Substring(...) on it, and "string myStr" if you don't.

    That's what a class is, after all. Something to call functions on. Which you do, on String objects.

  96. Avatar for Nyerguds
    Nyerguds June 28th, 2016

    These properties are all actually just functions that convert the internal value of the DateTime and return a piece of it. It is no different from calling Substring(...) on a string, besides the fact they have a predefined piece they cut out and return. It's the same as if you'd have properties like "FirstLetter" and "LastLetter" on a string.

  97. Avatar for Nyerguds
    Nyerguds June 28th, 2016

    Reference and value are unrelated to being nullable; String is nullable after all, and it is immutable just like DateTime.

    You know there's this really simple shortcut for "Nullable<datetime>", right? Just use "DateTime?"

  98. Avatar for Nyerguds
    Nyerguds June 28th, 2016

    Until you look a few programming language generations back and see that the word "int" referred to an Int16 instead, back then. Looks like a recipe for disaster to me, to keep using keywords with ambiguous meanings.

  99. Avatar for Nyerguds
    Nyerguds June 28th, 2016

    DateTime is actually a reference type, though, exactly like String. After all, It is more than just a single value; it contains a bunch of time zone related side objects besides the raw Ticks, and thus the actual value inside a DateTime variable is a reference address to said complex object, rather than containing the actual value of the thing itself.

    You might want to look deeper into the concept of "immutable types". On a related note, being non-nullable is also unrelated to the reference/value thing.

    Though I'd also turn down someone whose only explanation for defending his answer is the colour in the IDE ;)

  100. Avatar for Nyerguds
    Nyerguds June 28th, 2016

    These "primitive type" shortcuts have nothing to do with immutability (or nullability, as I've seen in some other comments around here too), though.

    Besides the special case of using "ref", immutability is the only factor that really determines whether a called function gets copies or references to originals.

    Plain fact is, there's not a single type in C# that doesn't have functions to call on it, making them all classes. The very concept of "primitive types" is simply obsolete, and code would be a lot cleaner if they were never used at all.

  101. Avatar for Nyerguds
    Nyerguds June 28th, 2016

    Consistency would be uppercase everywhere, actually. After all, all the other types use it <_<

  102. Avatar for Nyerguds
    Nyerguds June 28th, 2016

    The "var" thing is a setting that can be changed, but yes, its defaults are often awful.

  103. Avatar for Nyerguds
    Nyerguds June 28th, 2016

    Fully agree on the alias ambiguity. In fact, nowadays I see no real reason to still call anything "primitive types". They're all classes on which functions can be called, after all. C# has no such thing as "primitive types".

  104. Avatar for Nyerguds
    Nyerguds June 28th, 2016

    Peculiar. "Int32" immediately gives me the extra information that it's a 32-bit integer. Seems like something that would make it take less time to grasp the full implication of its use.

  105. Avatar for Ken Egozi
    Ken Egozi June 28th, 2016

    The distinction between reference and value types is quite clear. Reference (represented in c# as 'class') types' values live on the Heap, and a pointer to them is passed to method calls, while Value (represented in c# as 'struct' and primitives) types' values live on the Stack, and a *copy* of them is passed to methods.

    DateTime happens to be a struct (see http://referencesource.micr... hence a Value type. Entirely *not* like String which is a class (http://referencesource.micr... hence a Reference type.

    On a related note, there is a 1:1 correlation between *real* nullability and reference/value "thing". For that matter the .NET Nullable<> *struct* is a trick, a variable of which is never null, and when being compared to a null it would instead look into its .HasValue field.

  106. Avatar for Nyerguds
    Nyerguds June 28th, 2016

    Wow. That's mad. So DateTime is just a UInt64, with a couple of its bits reserved for special options? I'd have expected it to save that Calendar object if it were given in the constructor, but all it does with these objects is using them to calculate those ticks...

    Interesting stuff, thanks for linking.

  107. Avatar for Chris Rogers
    Chris Rogers June 28th, 2016

    No. When developers overwhelmingly use lowercase string/int/etc for their primitives (which they do), then it's definitely *not* consistent to sometimes use lowercase string and sometimes uppercase. Phil himself said that these primitives feel special (an opinion I share) - lowercase in all the codes ... not just sometimes.

  108. Avatar for dotnetchris
    dotnetchris June 28th, 2016

    You can mutate strings due to the internal implementation of a reference type emulating a primitive.

    Here's proof you can mutate strings

  109. Avatar for Nyerguds
    Nyerguds June 28th, 2016

    I dunno. The whole distinction of "primitives" seems rather useless to me. There's really no such thing in C#; it's all artificial. There's just structs and classes, and that doesn't even have a correlation with these aliases; String is a class, and DateTime is a struct, and I'm fairly sure you can simply make your own structs just like you can make your own classes anyway. Not even going into the confusing historical mess of the changing meanings of such types as "int", "short" and "long". Seems safer and a lot more clear to simply use "Int32" when you mean "Int32", then you'll always know in a single look that it's a 32-bit integer.

    Prevailing use is just up to education, in the end. People use it how they're taught to use it. MS just included these aliases for the programmers used to using such things from C++ I guess, but in my opinion it might've been better to simply not include them at all, and making camelcase the rule for all types, simple as that.

    And yes, I use "Int32" when writing my 'for' loops :p

  110. Avatar for Chris Rogers
    Chris Rogers June 28th, 2016

    This can certainly be an interesting topic from a theoretical perspective.
    But if the discussion is intended to relate to matters of practicality, then it must necessarily pay attention to established norms and conventions (be they right, wrong or neutral).

    While I don't have hard evidence to prove this, I'm reasonably confident that most coders wouldn't use Int32 in for loops. :-)
    From my experience, that's certainly an outlier and would only cause additional 'noise' for others required to maintain such code later.

  111. Avatar for Nyerguds
    Nyerguds June 28th, 2016

    I'll get back to you in 20 or 30 years, when "int" might be Int128, and the "int.MaxValue" in your code means something totally different :)

  112. Avatar for Chris Rogers
    Chris Rogers June 29th, 2016

    Most of the for-loops I've seen deal with sizes which aren't obscenely huge - as is the case with most other uses of int. The developer's mind can glide over the "int" without breaking stride. Whereas this is not the case when the width of the integer has been specifically dictated by the coder - this causes a brief mental disruption as one needs to consider whether there is significance in the developer's need to specify 32 or 64 bits.

    If size is ever likely to be important, then there is clearly a targeted requirement to specify such.
    If one ever anticipates needing an integer which may require 64 or 128 bit integers, then Int64/128 will be perfect! And in that case, the extra communication the code conveys is helpful. Until then, having to mentally pause to consider whether there is significance in the bit size is just annoying.

  113. Avatar for Chris Rogers
    Chris Rogers July 3rd, 2016

    A developer's mind is more able to glide over an "int" inside a loop than when the width of the integer has been explicitly specified by the original coder. Specifying Int32/64/128 causes a brief mental jarring to the developer reading the code, as they are required to ponder whether there is significance in the specified bit length.

    A for-loop from 0-10 that uses "Int32" instead of "int" is not only more verbose, but is trying to communicate more than is required, which is just plain annoying. When the size of the integer *really* doesn't matter (which is most of the time) - "Int32" provides no additional benefit - only additional noise.

    By all means, if/when the exact meaning of int.Max is ever likely to be relevant - then specifying the width is not only important, but actually highlights and communicates something of value. It draws the developers attention to something important.

    But in 20-30 years, if you ever find yourself thinking 128 bit integers will be required in your for-loop, I think you'll have bigger problems to deal with than getting back to me. :-)

  114. Avatar for William shepherd
    William shepherd October 19th, 2016

    So glad I am not the only one who feels this away about things that really shouldn't matter! I hate when I see string.IsNullOrEmpty(...) instead of String.IsNullOrEmpty(...).One says this is a static method and the other is saying a primitive is not just a primitive. Great to see others see code as communication to others in addition to the compiler :-)

  115. Avatar for Nyerguds
    Nyerguds March 4th, 2017

    Being able to hack into it doesn't change the fact the framework intends it to be immutable.