-
Notifications
You must be signed in to change notification settings - Fork 8
Common Pitfalls in C# Programming
A common pitfall is thinking that a value type is a reference type or vice versa. This can lead to unexpected behavior, especially when dealing with mutable value types or immutable reference types.
Value types are types that directly contain their data. When you assign a value type to a variable, the variable holds the actual data. When you pass a value type to a method, a copy of the data is passed.
-
Primitive Types:
int
,float
,double
,char
,bool
, etc. -
Structs: Custom types defined using the
struct
keyword.
int a = 10;
int b = a; // b is a copy of a
b = 20; // changing b does not affect a
Console.WriteLine(a); // Output: 10
Console.WriteLine(b); // Output: 20
Reference types are types that store a reference (or address) to the actual data. When you assign a reference type to a variable, the variable holds a reference to the data, not the data itself. When you pass a reference type to a method, a copy of the reference is passed, not the data.
-
Classes: Custom types defined using the
class
keyword. - Arrays: Even if the array contains value types, the array itself is a reference type.
-
Strings:
string
is a reference type, although it has some value-type-like behavior (immutability).
class MyClass
{
public int Value { get; set; }
}
MyClass obj1 = new MyClass { Value = 10 };
MyClass obj2 = obj1; // obj2 references the same object as obj1
obj2.Value = 20; // changing obj2 affects obj1
Console.WriteLine(obj1.Value); // Output: 20
Console.WriteLine(obj2.Value); // Output: 20
- Value types are copied by value.
- Reference types are copied by reference.
- Always be aware of whether you are dealing with a value type or a reference type to avoid unintended side effects.
When using lambda expressions, a common mistake is not capturing the intended variable within the lambda's scope. This can lead to unexpected behavior, especially when dealing with asynchronous operations or loops.
Consider the following code:
List<Action> actions = new List<Action>();
for (int i = 0; i < 5; i++)
{
actions.Add(() => Console.WriteLine(i));
}
foreach (var action in actions)
{
action();
}
0
1
2
3
4
5
5
5
5
5
- The variable
i
is shared across all iterations of the loop. - When the lambda is executed, it captures the current value of
i
, which is5
after the loop completes.
To capture the variable correctly, use a local copy within the loop:
for (int i = 0; i < 5; i++)
{
int copy = i;
actions.Add(() => Console.WriteLine(copy));
}
0
1
2
3
4
Always ensure that the variable you intend to capture is explicitly copied within the scope of the lambda to avoid unintended side effects.