Basically the compiler converts your code into something like this:
private string <__>firstName;
public string FirstName
{
get { return <__>firstName; }
set { <__>firstName = value; }
}
That's unlikely to be the exact name, but the use of angle brackets in the name is important - because it makes it an unspeakable name. (That's unofficial terminology, but widely used - I don't know whether Eric Lippert actually coined it, or whether he was just the first person to use it in something I read.) It's a name which isn't a valid C# identifier, but which the CLR is quite happy with. That has two benefits:
- The compiler doesn't need to worry about naming collisions with your identifiers
- The compiler doesn't need to worry about whether you're trying to refer to the field in your own code - you can't, because the name is unspeakable!
It uses the same technique for all kinds of other generated code - anonymous types, anonymous functions, iterator blocks etc.