Is Object Literal Instantiation faster than setting properties? [duplicate] - c#

This question already has answers here:
.NET object creation, whats faster?
(4 answers)
Closed 6 years ago.
Given the following example, is one objectively better/faster/safer than the other? Should object literal instantiation be a best practice where it is practical?
Where is this inappropriate?
class Person
{
public string name;
public int age;
}
void MakePeople()
{
Person myPerson = new Person();
myPerson.name = "Steve";
myPerson.age = 21;
Person literalPerson = new Person { name = "John", age = 22 };
}

No, it isn't faster or slower. It is the same.
The compiler translates object initializers to a constructor call followed by setting those properties.
Person literalPerson = new Person { name = "John", age = 22 };
Turns to:
Person myPerson = new Person();
myPerson.name = "John";
myPerson.age = 22;
You should use what is more readable and what you have agreed on with your team.

Either is appropriate. It depends on what you need to do to set properties. For example, I would avoid literal instantiation in cases where some logic is needed to arrive at a property value:
Person myPerson = new Person();
myPerson.SomeProperty = if IsNewPerson ? GetPropertyFromDatabase() : GetDefaultProperty();
Edit:
One advantage to using literal object initialization in Visual Studio is that Intellisense will prompt for properties, showing only those which have not already been declared. (I've ran into code where a value was redundantly assigned when setting properties.)

If you take a look at the IL that is generated, I'm pretty sure you'll find that they are identical. Using object initializers is just a compiler shortcut.

I don't think speed should be what drives this decision. There is probably very little difference between the speed of either method.
I think code readability should be the prime factor in which way you go. Using that criteria, I think they are very close and it comes down to personal preference or whatever your team decides on. However, I think in the case of a object with requires many properties to be set, explicitly calling setters is a little more readable.

Related

What does "initializing an instance of a class" mean?

After reading Meanings of declaring, instantiating, initializing and assigning an object it talks about what initializing a variable means. But it doesn't explain what "initializing" an instance of a class means.
public class Test
{
public static void Main()
{
Person person1 = new Person();
}
}
public class Person
{
// body
}
What does it mean to initialize an instance of a class?
Yeah, I don't like the "initialize" of the linked answer so much either, because it really only talks about giving a value to a single variable and doesn't really draw any distinctions between instantiation and assignment (the same lines of code are found in all of them) so for me it's a bit vague. We do have more specific processes (especially these days of modern c# syntax) when we talk about initialization
Initialize usually means "to give a created instance some initial values". Your class Person has nothing to initialize, so you could say that just by making it anew(instantiating) you've also done all the initialization possible and it's ready for use
Let's have something we can set values on
public class Person{
public string Name {get;set;}
public string Address {get;set;}
public Person(string name){
if(name == null) throw new ArgumentNullException(nameof(name));
Name = name;
}
}
Initializing as part of construction:
p = new Person("John");
Constructors force us to supply values and are used to ensure a developer gives a class the minimum set of data it needs to work.. a Person must have a name. Address is optional. We have created a person with the name initialized to John
Initializing post construction
You can give an instance additional (optional) values after you construct it, either like
p = new Person("Bill");
p.Address = "1 Microsoft Way";
Or
p = new Person("Bill"){
Address = "1 Microsoft Way"
}
Which is a syntactic sugar the compiler unrolls to something like the first. We refer to everything in the { } brackets of the second example as "an object initializer". An important distinction here though is that the first form (p.Address=...) is not considered to be initialization by the compiler. If you made the address property like:
public string Address {get;init;}
Then it can only be set in a constructor or in an object initializer, which is the latter form above. The p.Address=... form would result in a compiler error if the property were declared with init
Props set just after construction are part of the initialization process (as an English/linguistic thing) though I wouldn't call it init if it was any further down the line, such as
p = new Person("Sam");
string addr = Console.ReadLine();
p.Address = addr; //not initialization
You might find cases where people talk about initialization in the sense for "the first time a variable or property is given a value" but that's also more a linguistic/English thing than a c# thing
The compiler knows how to perform other initialization, so we also call things like this "an initializer":
string[] x = new string[] {"a","b","c"};
The process of giving the array those 3 values is initialization, and the compiler will even take the type of the first argument and use it to make the array type, so an array can be type declared and ignited from the data:
var x = new[] {"a","b","c"};

Why reference types inside structs behave like value types?

I am a beginner to C# programming. I am now studying strings, structs, value types and reference types. As accepted answers in here and in here, strings are reference types that have pointers stored on stack while their actual contents stored on heap. Also, as claimed in here, structs are value types. Now I try to practice with structs and strings with a small example:
struct Person
{
public string name;
}
class Program
{
static void Main(string[] args)
{
Person person_1 = new Person();
person_1.name = "Person 1";
Person person_2 = person_1;
person_2.name = "Person 2";
Console.WriteLine(person_1.name);
Console.WriteLine(person_2.name);
}
}
The above code snippet outputs
Person 1
Person 2
that makes me confused. If strings are reference types and structs are value types then person_1.name and person_2.name should point to the same space region on heap, shouldn't them?
strings are reference types that have pointers stored on stack while their actual contents stored on heap
No no no. First off, stop thinking about stack and heap. This is almost always the wrong way to think in C#. C# manages storage lifetime for you.
Second, though references may be implemented as pointers, references are not logically pointers. References are references. C# has both references and pointers. Don't mix them up. There is no pointer to string in C#, ever. There are references to string.
Third, a reference to a string could be stored on the stack but it could also be stored on the heap. When you have an array of references to string, the array contents are on the heap.
Now let's come to your actual question.
Person person_1 = new Person();
person_1.name = "Person 1";
Person person_2 = person_1; // This is the interesting line
person_2.name = "Person 2";
Let's illustrate what the code does logically. Your Person struct is nothing more than a string reference, so your program is the same as:
string person_1_name = null; // That's what new does on a struct
person_1_name = "Person 1";
string person_2_name = person_1_name; // Now they refer to the same string
person_2_name = "Person 2"; // And now they refer to different strings
When you say person2 = person1 that does not mean that the variable person1 is now an alias for the variable person2. (There is a way to do that in C#, but this is not it.) It means "copy the contents of person1 to person2". The reference to the string is the value that is copied.
If that's not clear try drawing boxes for variables and arrows for references; when the struct is copied, a copy of the arrow is made, not a copy of the box.
The best way to understand this is to fully understand what variables are; variables are, simply put, placeholders that hold values.
So what exactly is this value? In a reference type, the value stored in the variable is the reference (the address so to speak) to a given object. In a value type, the value is the object itself.
When you do AnyType y = x; what really happens is that a copy of the value stored in x is made and is then stored in y.
So if x is a reference type, both x and y will point to the same object because they will both hold identical copies of the same reference. If x is a value type then both x and y will hold two identical but distinct objects.
Once you understand this, it should start to make sense why your code behaves the way it does. Lets study it step by step:
Person person_1 = new Person();
Ok we are creating a new instance of a value type. According to what I explained previously, the value stores in person_1 is the newly created object itself. Where this value is stored (heap or stack) is an implementation detail, its not relevant at all to how your code behaves.
person_1.name = "Person 1";
Now we are setting the variable name which happens to be a field of person_1. Again according to previous explanations, the value of name is a reference pointing to somewhere in memory where the string "Person 1" is stored. Again, where the value or the string are stored is irrelevant.
Person person_2 = person_1;
Ok, this is the interesting part. What happens here? Well, a copy of the value stored in person_1 is made and stored in person_2. Because the value happens to be an instance of a value type, a new copy of said instance is created and stored in person_2. This new copy has its own field name and the value stored in this variable is, again, a copy of the value stored in person_1.name (a reference to "Person 1").
person_2.name = "Person 2";
Now we are simply reassigning the variable person_2.name. This means we are storing a new reference that points to a new string somewhere in memory. Do note, that person_2.name originally held a copy of the value stored in person_1.name so whatever you do to person_2.name has no effect on whatever value is stored in person_1.name because you are simply changing... yeah exactly, a copy. And thats why your code behaves the way it does.
As an exercise, try to reason out in a similar way how your code would behave if Person were a reference type.
Each struct instance has it's own fields. person_1.name is an independent variable from person_2.name. These are not static fields.
person_2 = person_1 copies the struct by value.
The fact that string is immutable is not required to explain this behavior.
Here's the same case with a class instead to demonstrate the difference:
class C { public string S; }
C c1 = new C();
C c2 = c1; //copy reference, share object
c1.S = "x"; //it appears that c2.S has been set simultaneously because it's the same object
Here, c1.S and c2.S refer to the same variable. If you make this a struct then they become different variables (as in your code). c2 = c1 then turns in a copy of the struct value where it previously was a copy of an object reference.
Think of strings are arrays of characters. The code below is similar to yours, but with arrays.
public struct Lottery
{
public int[] numbers;
}
public static void Main()
{
var A = new Lottery();
A.numbers = new[] { 1,2,3,4,5 };
// struct A is in the stack, and it contains one reference to an array in RAM
var B = A;
// struct B also is in the stack, and it contains a copy of A.numbers reference
B.numbers[0] = 10;
// A.numbers[0] == 10, since both A.numbers and B.numbers point to same memory
// You can't do this with strings because they are immutable
B.numbers = new int[] { 6,7,8,9,10 };
// B.numbers now points to a new location in RAM
B.numbers[0] = 60;
// A.numbers[0] == 10, B.numbers[0] == 60
// The two structures A and B *are completely separate* now.
}
So if you have a structure that contains references (strings, arrays or classes) and you want to implement ICloneable make sure you also clone the contents of the references.
public class Person : ICloneable
{
public string Name { get; set; }
public Person Clone()
{
return new Person() { Name=this.Name }; // string copy
}
object ICloneable.Clone() { return Clone(); } // interface calls specific function
}
public struct Project : ICloneable
{
public Person Leader { get; set; }
public string Name { get; set; }
public int[] Steps { get; set; }
public Project Clone()
{
return new Project()
{
Leader=this.Leader.Clone(), // calls Clone for copy
Name=this.Name, // string copy
Steps=this.Steps.Clone() as int[] // shallow copy of array
};
}
object ICloneable.Clone() { return Clone(); } // interface calls specific function
}
I would highlight the fact, that by person_2.name = "Person 2" we are actually creating a new string object in the memory that contains the value "Person 2", and we are asigning the reference of this object. You can imagine it as following:
class StringClass
{
string value; //lets imagine this is a "value type" string, so it's like int
StringClass(string value)
{
this.value = value
}
}
By person_2.name = "Person 2" you are actually doing something like person_2.name = new StringClass("Person 2"), whilst "name" holds just a value which represents an address in a memory
Now if I rewrite your code:
struct Person
{
public StringClass name;
}
class Program
{
static void Main(string[] args)
{
Person person_1 = new Person();
person_1.name = new String("Person 1"); //imagine the reference value of name is "m1", which points somewhere into the memory where "Person 1" is saved
Person person_2 = person_1; //person_2.name holds the same reference, that is "m1" that was copied from person_1.name
person_2.name = new String("Person 2"); //person_2.name now holds a new reference "m2" to a new StringClass object in the memory, person_1.name still have the value of "m1"
person_1.name = person_2.name //this copies back the new reference "m2" to the original struct
Console.WriteLine(person_1.name);
Console.WriteLine(person_2.name);
}
}
Now the output of the snippet:
Person 2
Person 2
To be able to change person_1.name the way you originally posted in your snippet in a struct you would need to use ref https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/ref
I think a lot of the answers here miss the point of the original question, mainly because the example was not really good. Some answers point to the immutability of strings as the correct cause of this behaviour, but in the question of the op that indeed would not have made a difference.
A better example to illustrate some confusion I have seen in my dev teams over strings would have been:
class SomeClass
{
public int SomeNumber;
}
struct Person
{
public string name;
public SomeClass someClass;
}
class Program
{
static void Main(string[] args)
{
Person person_1 = new Person();
person_1.someClass = new SomeClass()
{
SomeNumber = 4,
};
person_1.name = "Person 1";
Person person_2 = person_1;
person_2.name += " changed";
person_2.someClass.SomeNumber += 1;
Console.WriteLine(person_1.name);
Console.WriteLine(person_2.name);
Console.WriteLine(person_1.someClass.SomeNumber);
Console.WriteLine(person_2.someClass.SomeNumber);
}
}
In this example the output would be
Person 1
Person 1 changed
5
5
The question of the op was, if both instances of objects and strings are reference types, then why do they behave differently when copied around. The correct answer in this example would indeed be because strings are immutable.
Person person_2 = person_1; // at this point the properties of person_2 both point to the same memory location as those of person 1. this is because person_1 is copied by value to person_2, the references are the values being copied, not what they point to (no deep copy)
person_2.name += " changed"; // strings are immutable, so the first string is not changed, instead a new memory location is allocated, the characters are stored and a new reference to that location is stored in the second struct
person_2.someClass.SomeNumber += 1; // nothing here changes the reference of someClass, thus both structs reflect this new value
I hope this clears up some confusion for people still wondering about this.

Use object initializer - Resharper suggestion

I use ReSharper everyday, and today I asked myself why ReSharper suggests "Use object initializer" when I do this :
MyClass myClass = new MyClass();
myClass.MyInt = 0;
myClass.MyString = string.Empty;
It gets replaced by :
MyClass myClass = new MyClass
{
MyInt = 0,
MyString = string.Empty
};
Does this optimize the execution of my code, or is it just a matter of reformatting?
Personally, I like it. But sometimes I hate it, because of this :
I can't do step-by-step debugging :(
The second contains less characters and so is more compact to read. You don't have to repeat myClass 2 more times, and the initialization logic is in one block.
It is really a syntactic sugar that doesn't change a thing in the generated code. If you doesn't like it, you can always disable the warning on ReSharper.
A longer post on the advantages of using Object Initializers here:
Setting properties via object initialization or not : Any difference ?
Is there any benefit of using an Object Initializer?
You can do step-by-step debugging partially if initializers are function calls:
MyClass c = new MyClass()
{
MyInt = 3,
MyString = GenerateString(9)
};
In this case, F11 will lead you straight into the GenerateString method.
EDIT: If initializers are simple values, then step-by-step debugging is meaningless anyway.

Use of var and default for declaration in C#

Recently I saw a person heavily using var and default keywords for declaration of variables (and for every declaration), something like this:
var employee = default(Employee); //Employee is a class
var errorInfo = default(ErrorInfo); //ErrorInfo is struct; Blank is default value
var salary = default(Double);
var isManager = default(Boolean?);
instead of using:
Employee employee = null; //Employee is a class
ErrorInfo errorInfo = Blank; //ErrorInfo is struct; Blank is default value
Double salary = 0.0;
Boolean? isManager = null;
or, instead of using even:
Employee employee; //Employee is a class
ErrorInfo errorInfo; //ErrorInfo is struct; Blank is default value
Double salary;
Boolean? isManager;
Now using var and default for declaration for every variable is something i am not accustomed to.
Want to know:
- If this is a recommended practice?
- Your views and preference?
PS:
- Have gone through Use of var keyword in C#, Use of "var" type in variable declaration and https://stackoverflow.com/questions/633474/c-do-you-use-var, however, think that this question although related is slightly different as it is solely around declaration/initialization and not around assignment.
- I understand the difference between snipped 2 and snippet 3. However, question is more around snippet 1.
- If you strongly feel that this question belongs to programmers stackexchange feel free to move.
I'm not going to say anything about "var" there have been comments and discussions about this in the past (sufficiently so ;-)
Concerning "default()" I would not use this to initialize a known type, but rather only in generics. There it helps to transparently handle value types or reference types by allowing you to provide a default (return) value or can be used in comparisons.
Well, the default keyword isn't the most used keyword I think, and in my opinion it serves its purpose best in terms of Generics, like so:
public class Foo<T>{
private T _instance;
public Foo<T>(){
_instance = default(T);
}
}
in order to get a new default instance of T.
There are really no reasons to use it like scenario 1 in your post.
Using var however is a different question, and many view this as a matter of readability. I default to var when I write code simply because I find it easier to read:
var me = new Person();
It seems a bit redundant in terms of readability to do
Person me = new Person();
Another case I recommend var is if something changes. Consider the following example:
public decimal Calculate(decimal one, decimal two){
return one + two;
}
And somewhere else in your code:
decimal d = Calculate(1M, 2M);
If you for some reason change the return type of Calculate to, say, double you need to change all the places where you strongly defined the variable.
If you instead do
var d = Calculate(1M, 2M)
you don't have to worry about this. The Double/Decimal example is a bit simple, but in terms of refactoring and interfacing out classes, I've found this very useful.
I think this is bad practice which will prevent the compiler (and 3rd party tools) from catching bugs related to failure to initialize a variable. Generally I try to keep declaration and assignment as close to each other as possible. Assigning values that aren't intended to be used to variables can potentially introduce subtle bugs that are difficult to catch. Normally I'd either:
SomeType variable1; //want to store something that will be out of scope later
using(blah)
{
//...
variable1=blah;
}
//use variable1 here
or assign required value immediately:
SomeType variable2 = new SomeType();
//use variable2 immediately
or (for me, more frequently nowdays)
var variable2 = new SomeType();
assigning null/placeholder values is mainly pointless.
I use var for assignment. However I always declare instances using the class. I generally also instantiate them at the time to avoid unexpected NullReferenceExceptions
The code is ok.
Just make sure that you don't copy this technique to initialize enums where 0 is not default value or flagged enumerations.
[Flags]
public enum MyFlags
{
Test = 1,
Test2 = 2
}
MyFlags flags = default(MyFlags);
Console.WriteLine(flags); // oops

What are your favorite little used C# trick? [duplicate]

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 11 years ago.
Locked. This question and its answers are locked because the question is off-topic but has historical significance. It is not currently accepting new answers or interactions.
This came to my mind after I learned the following from this question:
where T : struct
We, C# developers, all know the basics of C#. I mean declarations, conditionals, loops, operators, etc.
Some of us even mastered the stuff like Generics, anonymous types, lambdas, LINQ, ...
But what are the most hidden features or tricks of C# that even C# fans, addicts, experts barely know?
Here are the revealed features so far:
Keywords
yield by Michael Stum
var by Michael Stum
using() statement by kokos
readonly by kokos
as by Mike Stone
as / is by Ed Swangren
as / is (improved) by Rocketpants
default by deathofrats
global:: by pzycoman
using() blocks by AlexCuse
volatile by Jakub Šturc
extern alias by Jakub Šturc
Attributes
DefaultValueAttribute by Michael Stum
ObsoleteAttribute by DannySmurf
DebuggerDisplayAttribute by Stu
DebuggerBrowsable and DebuggerStepThrough by bdukes
ThreadStaticAttribute by marxidad
FlagsAttribute by Martin Clarke
ConditionalAttribute by AndrewBurns
Syntax
?? (coalesce nulls) operator by kokos
Number flaggings by Nick Berardi
where T:new by Lars Mæhlum
Implicit generics by Keith
One-parameter lambdas by Keith
Auto properties by Keith
Namespace aliases by Keith
Verbatim string literals with # by Patrick
enum values by lfoust
#variablenames by marxidad
event operators by marxidad
Format string brackets by Portman
Property accessor accessibility modifiers by xanadont
Conditional (ternary) operator (?:) by JasonS
checked and unchecked operators by Binoj Antony
implicit and explicit operators by Flory
Language Features
Nullable types by Brad Barker
Anonymous types by Keith
__makeref __reftype __refvalue by Judah Himango
Object initializers by lomaxx
Format strings by David in Dakota
Extension Methods by marxidad
partial methods by Jon Erickson
Preprocessor directives by John Asbeck
DEBUG pre-processor directive by Robert Durgin
Operator overloading by SefBkn
Type inferrence by chakrit
Boolean operators taken to next level by Rob Gough
Pass value-type variable as interface without boxing by Roman Boiko
Programmatically determine declared variable type by Roman Boiko
Static Constructors by Chris
Easier-on-the-eyes / condensed ORM-mapping using LINQ by roosteronacid
__arglist by Zac Bowling
Visual Studio Features
Select block of text in editor by Himadri
Snippets by DannySmurf
Framework
TransactionScope by KiwiBastard
DependantTransaction by KiwiBastard
Nullable<T> by IainMH
Mutex by Diago
System.IO.Path by ageektrapped
WeakReference by Juan Manuel
Methods and Properties
String.IsNullOrEmpty() method by KiwiBastard
List.ForEach() method by KiwiBastard
BeginInvoke(), EndInvoke() methods by Will Dean
Nullable<T>.HasValue and Nullable<T>.Value properties by Rismo
GetValueOrDefault method by John Sheehan
Tips & Tricks
Nice method for event handlers by Andreas H.R. Nilsson
Uppercase comparisons by John
Access anonymous types without reflection by dp
A quick way to lazily instantiate collection properties by Will
JavaScript-like anonymous inline-functions by roosteronacid
Other
netmodules by kokos
LINQBridge by Duncan Smart
Parallel Extensions by Joel Coehoorn
This isn't C# per se, but I haven't seen anyone who really uses System.IO.Path.Combine() to the extent that they should. In fact, the whole Path class is really useful, but no one uses it!
I'm willing to bet that every production app has the following code, even though it shouldn't:
string path = dir + "\\" + fileName;
lambdas and type inference are underrated. Lambdas can have multiple statements and they double as a compatible delegate object automatically (just make sure the signature match) as in:
Console.CancelKeyPress +=
(sender, e) => {
Console.WriteLine("CTRL+C detected!\n");
e.Cancel = true;
};
Note that I don't have a new CancellationEventHandler nor do I have to specify types of sender and e, they're inferable from the event. Which is why this is less cumbersome to writing the whole delegate (blah blah) which also requires you to specify types of parameters.
Lambdas don't need to return anything and type inference is extremely powerful in context like this.
And BTW, you can always return Lambdas that make Lambdas in the functional programming sense. For example, here's a lambda that makes a lambda that handles a Button.Click event:
Func<int, int, EventHandler> makeHandler =
(dx, dy) => (sender, e) => {
var btn = (Button) sender;
btn.Top += dy;
btn.Left += dx;
};
btnUp.Click += makeHandler(0, -1);
btnDown.Click += makeHandler(0, 1);
btnLeft.Click += makeHandler(-1, 0);
btnRight.Click += makeHandler(1, 0);
Note the chaining: (dx, dy) => (sender, e) =>
Now that's why I'm happy to have taken the functional programming class :-)
Other than the pointers in C, I think it's the other fundamental thing you should learn :-)
From Rick Strahl:
You can chain the ?? operator so that you can do a bunch of null comparisons.
string result = value1 ?? value2 ?? value3 ?? String.Empty;
Aliased generics:
using ASimpleName = Dictionary<string, Dictionary<string, List<string>>>;
It allows you to use ASimpleName, instead of Dictionary<string, Dictionary<string, List<string>>>.
Use it when you would use the same generic big long complex thing in a lot of places.
From CLR via C#:
When normalizing strings, it is highly
recommended that you use
ToUpperInvariant instead of
ToLowerInvariant because Microsoft has
optimized the code for performing
uppercase comparisons.
I remember one time my coworker always changed strings to uppercase before comparing. I've always wondered why he does that because I feel it's more "natural" to convert to lowercase first. After reading the book now I know why.
My favorite trick is using the null coalesce operator and parentheses to automagically instantiate collections for me.
private IList<Foo> _foo;
public IList<Foo> ListOfFoo
{ get { return _foo ?? (_foo = new List<Foo>()); } }
Avoid checking for null event handlers
Adding an empty delegate to events at declaration, suppressing the need to always check the event for null before calling it is awesome. Example:
public delegate void MyClickHandler(object sender, string myValue);
public event MyClickHandler Click = delegate {}; // add empty delegate!
Let you do this
public void DoSomething()
{
Click(this, "foo");
}
Instead of this
public void DoSomething()
{
// Unnecessary!
MyClickHandler click = Click;
if (click != null) // Unnecessary!
{
click(this, "foo");
}
}
Please also see this related discussion and this blog post by Eric Lippert on this topic (and possible downsides).
Everything else, plus
1) implicit generics (why only on methods and not on classes?)
void GenericMethod<T>( T input ) { ... }
//Infer type, so
GenericMethod<int>(23); //You don't need the <>.
GenericMethod(23); //Is enough.
2) simple lambdas with one parameter:
x => x.ToString() //simplify so many calls
3) anonymous types and initialisers:
//Duck-typed: works with any .Add method.
var colours = new Dictionary<string, string> {
{ "red", "#ff0000" },
{ "green", "#00ff00" },
{ "blue", "#0000ff" }
};
int[] arrayOfInt = { 1, 2, 3, 4, 5 };
Another one:
4) Auto properties can have different scopes:
public int MyId { get; private set; }
Thanks #pzycoman for reminding me:
5) Namespace aliases (not that you're likely to need this particular distinction):
using web = System.Web.UI.WebControls;
using win = System.Windows.Forms;
web::Control aWebControl = new web::Control();
win::Control aFormControl = new win::Control();
I didn't know the "as" keyword for quite a while.
MyClass myObject = (MyClass) obj;
vs
MyClass myObject = obj as MyClass;
The second will return null if obj isn't a MyClass, rather than throw a class cast exception.
Two things I like are Automatic properties so you can collapse your code down even further:
private string _name;
public string Name
{
get
{
return _name;
}
set
{
_name = value;
}
}
becomes
public string Name { get; set;}
Also object initializers:
Employee emp = new Employee();
emp.Name = "John Smith";
emp.StartDate = DateTime.Now();
becomes
Employee emp = new Employee {Name="John Smith", StartDate=DateTime.Now()}
The 'default' keyword in generic types:
T t = default(T);
results in a 'null' if T is a reference type, and 0 if it is an int, false if it is a boolean,
etcetera.
Attributes in general, but most of all DebuggerDisplay. Saves you years.
The # tells the compiler to ignore any
escape characters in a string.
Just wanted to clarify this one... it doesn't tell it to ignore the escape characters, it actually tells the compiler to interpret the string as a literal.
If you have
string s = #"cat
dog
fish"
it will actually print out as (note that it even includes the whitespace used for indentation):
cat
dog
fish
I think one of the most under-appreciated and lesser-known features of C# (.NET 3.5) are Expression Trees, especially when combined with Generics and Lambdas. This is an approach to API creation that newer libraries like NInject and Moq are using.
For example, let's say that I want to register a method with an API and that API needs to get the method name
Given this class:
public class MyClass
{
public void SomeMethod() { /* Do Something */ }
}
Before, it was very common to see developers do this with strings and types (or something else largely string-based):
RegisterMethod(typeof(MyClass), "SomeMethod");
Well, that sucks because of the lack of strong-typing. What if I rename "SomeMethod"? Now, in 3.5 however, I can do this in a strongly-typed fashion:
RegisterMethod<MyClass>(cl => cl.SomeMethod());
In which the RegisterMethod class uses Expression<Action<T>> like this:
void RegisterMethod<T>(Expression<Action<T>> action) where T : class
{
var expression = (action.Body as MethodCallExpression);
if (expression != null)
{
// TODO: Register method
Console.WriteLine(expression.Method.Name);
}
}
This is one big reason that I'm in love with Lambdas and Expression Trees right now.
"yield" would come to my mind. Some of the attributes like [DefaultValue()] are also among my favorites.
The "var" keyword is a bit more known, but that you can use it in .NET 2.0 applications as well (as long as you use the .NET 3.5 compiler and set it to output 2.0 code) does not seem to be known very well.
Edit: kokos, thanks for pointing out the ?? operator, that's indeed really useful. Since it's a bit hard to google for it (as ?? is just ignored), here is the MSDN documentation page for that operator: ?? Operator (C# Reference)
I tend to find that most C# developers don't know about 'nullable' types. Basically, primitives that can have a null value.
double? num1 = null;
double num2 = num1 ?? -100;
Set a nullable double, num1, to null, then set a regular double, num2, to num1 or -100 if num1 was null.
http://msdn.microsoft.com/en-us/library/1t3y8s4s(VS.80).aspx
one more thing about Nullable type:
DateTime? tmp = new DateTime();
tmp = null;
return tmp.ToString();
it is return String.Empty. Check this link for more details
Here are some interesting hidden C# features, in the form of undocumented C# keywords:
__makeref
__reftype
__refvalue
__arglist
These are undocumented C# keywords (even Visual Studio recognizes them!) that were added to for a more efficient boxing/unboxing prior to generics. They work in coordination with the System.TypedReference struct.
There's also __arglist, which is used for variable length parameter lists.
One thing folks don't know much about is System.WeakReference -- a very useful class that keeps track of an object but still allows the garbage collector to collect it.
The most useful "hidden" feature would be the yield return keyword. It's not really hidden, but a lot of folks don't know about it. LINQ is built atop this; it allows for delay-executed queries by generating a state machine under the hood. Raymond Chen recently posted about the internal, gritty details.
Unions (the C++ shared memory kind) in pure, safe C#
Without resorting to unsafe mode and pointers, you can have class members share memory space in a class/struct. Given the following class:
[StructLayout(LayoutKind.Explicit)]
public class A
{
[FieldOffset(0)]
public byte One;
[FieldOffset(1)]
public byte Two;
[FieldOffset(2)]
public byte Three;
[FieldOffset(3)]
public byte Four;
[FieldOffset(0)]
public int Int32;
}
You can modify the values of the byte fields by manipulating the Int32 field and vice-versa. For example, this program:
static void Main(string[] args)
{
A a = new A { Int32 = int.MaxValue };
Console.WriteLine(a.Int32);
Console.WriteLine("{0:X} {1:X} {2:X} {3:X}", a.One, a.Two, a.Three, a.Four);
a.Four = 0;
a.Three = 0;
Console.WriteLine(a.Int32);
}
Outputs this:
2147483647
FF FF FF 7F
65535
just add
using System.Runtime.InteropServices;
Using # for variable names that are keywords.
var #object = new object();
var #string = "";
var #if = IpsoFacto();
If you want to exit your program without calling any finally blocks or finalizers use FailFast:
Environment.FailFast()
Returning anonymous types from a method and accessing members without reflection.
// Useful? probably not.
private void foo()
{
var user = AnonCast(GetUserTuple(), new { Name = default(string), Badges = default(int) });
Console.WriteLine("Name: {0} Badges: {1}", user.Name, user.Badges);
}
object GetUserTuple()
{
return new { Name = "dp", Badges = 5 };
}
// Using the magic of Type Inference...
static T AnonCast<T>(object obj, T t)
{
return (T) obj;
}
Here's a useful one for regular expressions and file paths:
"c:\\program files\\oldway"
#"c:\program file\newway"
The # tells the compiler to ignore any escape characters in a string.
Mixins. Basically, if you want to add a feature to several classes, but cannot use one base class for all of them, get each class to implement an interface (with no members). Then, write an extension method for the interface, i.e.
public static DeepCopy(this IPrototype p) { ... }
Of course, some clarity is sacrificed. But it works!
Not sure why anyone would ever want to use Nullable<bool> though. :-)
True, False, FileNotFound?
This one is not "hidden" so much as it is misnamed.
A lot of attention is paid to the algorithms "map", "reduce", and "filter". What most people don't realize is that .NET 3.5 added all three of these algorithms, but it gave them very SQL-ish names, based on the fact that they're part of LINQ.
"map" => Select Transforms data
from one form into another
"reduce" => Aggregate Aggregates
values into a single result
"filter" => Where Filters data
based on a criteria
The ability to use LINQ to do inline work on collections that used to take iteration and conditionals can be incredibly valuable. It's worth learning how all the LINQ extension methods can help make your code much more compact and maintainable.
Environment.NewLine
for system independent newlines.
If you're trying to use curly brackets inside a String.Format expression...
int foo = 3;
string bar = "blind mice";
String.Format("{{I am in brackets!}} {0} {1}", foo, bar);
//Outputs "{I am in brackets!} 3 blind mice"
?? - coalescing operator
using (statement / directive) - great keyword that can be used for more than just calling Dispose
readonly - should be used more
netmodules - too bad there's no support in Visual Studio
#Ed, I'm a bit reticent about posting this as it's little more than nitpicking. However, I would point out that in your code sample:
MyClass c;
if (obj is MyClass)
c = obj as MyClass
If you're going to use 'is', why follow it up with a safe cast using 'as'? If you've ascertained that obj is indeed MyClass, a bog-standard cast:
c = (MyClass)obj
...is never going to fail.
Similarly, you could just say:
MyClass c = obj as MyClass;
if(c != null)
{
...
}
I don't know enough about .NET's innards to be sure, but my instincts tell me that this would cut a maximum of two type casts operations down to a maximum of one. It's hardly likely to break the processing bank either way; personally, I think the latter form looks cleaner too.
Maybe not an advanced technique, but one I see all the time that drives me crazy:
if (x == 1)
{
x = 2;
}
else
{
x = 3;
}
can be condensed to:
x = (x==1) ? 2 : 3;

Categories

Resources