What makes String different from other classes (treating String as a value type)? RRS feed

  • Question

  • There's something that I've never really been able to wrap my head around, and I'm hoping I can get some help.  I'm doing some work that requires using reflection to walk the properties of a class, and I need to generically tell the difference between a property that is something like a String and a property whose type is one of my own classes.

    My specific situation is that I'm walking a client-side entity class used in conjunction with ADO.NET Data Services.  Properties that are references to object instances are represented by "links" to those objects.  Value types (like int) do not require links. 

    Consider a class like "Employee" with a reference to a separate "Department" instance.  Employee has String properties like FirstName and LastName.  It has a property named "Department" that is a reference to an instance of Department.  It is clear that you can simply set FirstName and LastName and not worry about establishing a link to some external instance of String.  For the Department property, I have to establish a link to an external instance of Department.

    So they are clearly treated differently.  The String properties act more like Value types.  But obviously String itself is a class, just like Department is a class.  The PropertyInfo objects for FirstName and Department look very similar.  But the behavior of these two properties in practice is quite different.

    So what is that difference?  I could obviously just have code that says "if the property is-a String, do something different", but that's obviously not the right answer.  There's must be something about String that distinguishes it from my plain-old CLR object "Department", but I can't put my finger on what that is. 

    I'm sure this question is basic.  Can someone help me with it?


    David Cater
    Thursday, August 14, 2008 3:17 PM

All replies

  • > It is clear that you can simply set FirstName and LastName and not worry about establishing a link to some external instance of String. 

    The system creates an instance of String and assigns a reference to it.  (Note:  In reality, to improve effficiency, it often reuses an existing instance of String that already has the same contents.  It can do this because Strings are "immutable" -- the characters in any given String never change after the String object is constructed.)

    To convince yourself of this, consider that you can write code like the following:

    obj.Text = new String(new Char[] { 'H', 'e', 'l', 'l', 'o' }); 

    The most special thing is that most literals that appear in programs (such as numbers) are value types.  However, strings are an special case since they are reference types yet still can be specified by literals.

    Friday, August 15, 2008 12:38 AM
  • It has to do with the overloading of Operator== and Operator!=.  For the string class they are designed to operator on the value of the class and not the reference.  Check out

    Michael Fischer
    Friday, August 15, 2008 12:49 AM
  • Thanks a lot for both answers.  That definitely expands my knowledge about the String class. 

    In both of those cases, though, the features discussed (assignment and equality checks) represent additional features added to the String class that make String variables easier to work with. 

    But those features don't really affect the information you would see about the String class using reflection (unless you actually looked for the overloaded equality operators).  So I don't think that quite addresses my core question, which is how an algorithm that depends on using Reflection to walk the properties of an object would distinguish between a String property like "FirstName" that it can sort of treat as a value type and a Department property like "Department" that it can't. 

    But I'm starting to wonder if my question even makes sense.  Right now I have two theories about what's going on:

    1. The distinction between "Department" and "FirstName" has nothing to do with the fact that FirstName is a String and Department is not.  Instead, the code that is walking the Employee object knows that Department objects are something that it manages as external references that need to be linked to and therefore treated differently.  That might be the case in ADO.NET Data Services, because it could know that Department is a first-class entity (that ultimately maps to a database table), where as FirstName is not a first-class entity.  The distinction in this case then is between managed and not-managed, as opposed to String and not-String.
    2. In some environments this could be a conversion issue, where certain types are convertible to/from strings.  So if I added a TypeConverter that could handle converting Department objects to/from strings and decorated Department with a [TypeConverter] attribute, then it could be treated more like a value object just like FirstName.  That might be the functionality that comes into play when serializing properties to/from Xml, for example.  Currently Department might require a separate subtree when it is serialized to account for all of its public properties, whereas a converter might allow the entire Department to be serialized as a single Xml node.  The distinction in this case would then be between "Convertible-To-String" and "Not-Convertible-To-String" as opposed to String and not-String.


    • Edited by David Cater Friday, August 15, 2008 1:08 AM reword
    Friday, August 15, 2008 1:07 AM