Sometimes new features are added to a language which fundamentally change how we do things (e.g., when generics was added to .NET 2.0). However, there are other times when features are added to the language that are "syntax sugar" or "nice to have's". My outlook on those items has always been that "syntax sugar" is typically a good thing – if there is some feature that allows the code to be more expressive/readable then that is a great thing. Sure, the IL might not be any different behind the scenes but you want your code to be as understandable as possible and developers that come behind you can easily understand what your intent was.
To that end, I believe that named parameters being added to C# 4.0 is a good thing. I'm certainly not advocating that named parameters be used for every method call but there are several instances where this is going to be helpful in terms of code readabilty. Often you see argument passed to a method and you have no idea what the parameters are for. Brad Abrams has a nice design guidelines post regarding Enums vs bool arguments which talks about this very thing. He discusses that enums are often a better choice than Boolean for method parameters because they express intent more clearly. So in the case where you can't control the method you are already calling, you can use named parameters to better express intent.
Consider this line of code:
File.Copy("source.txt", "destination.txt", true);
Unless you're a developer that is already familiar with this method, you can only guess as to what the last Boolean parameter is for. With C# 4.0 named parameters this code can be written like this to more clearly express intent:
File.Copy("source.txt", "destination.txt", overwrite: true);
Object initializers, while typically used in the context of LINQ, can also be used as a stand-alone language feature to express intent more clearly. For example, this snippet of code:
Person person = new Person(); person.FirstName = "John"; person.LastName = "Smith"; person.DateOfBirth = new DateTime(1970, 1, 1);
can be re-written with object initializers like this to be more concise and better express intent:
Person person = new Person() { FirstName = "John", LastName="Smith", DateOfBirth = new DateTime(1970, 1, 1)};
It's as if you can use constructor like syntax to initialize the object – but it's more readable than a constructor because the object initializer uses the property names so it's obvious what is happening and what properties are being assigned to. Of course, you can only use that type of syntax in C# 3.0 IF all three of those properties have publicly accessible setters. What happens if you actually do have a constructor definition that looks like this:
public Person(string firstName, string lastName, DateTime dateOfBirth)
In that case, you have no other option in C# 3.0 other than to invoke the constructor like this:
Person person = new Person("John", "Smith", new DateTime(1970, 1, 1));
So it's not 100% obvious what is being assigned in the constructor (e.g., that third DateTime parameter might be date of birth, might be date hired, who knows). In C# 4.0, you can invoke the constructor like this:
Person person = new Person(firstName: "John", lastName: "Smith", dateOfBirth: new DateTime(1970, 1, 1));
This expresses intent clearly and makes the code more understandable. Again, named parameters should not be used gratuitously but there are many instances where it can make your code higher quality.