Discard feature significance in C# 7.0? - c#

While going through new C# 7.0 features, I stuck up with discard feature. It says:
Discards are local variables which you can assign but cannot read
from. i.e. they are “write-only” local variables.
and, then, an example follows:
if (bool.TryParse("TRUE", out bool _))
What is real use case when this will be beneficial? I mean what if I would have defined it in normal way, say:
if (bool.TryParse("TRUE", out bool isOK))

The discards are basically a way to intentionally ignore local variables which are irrelevant for the purposes of the code being produced. It's like when you call a method that returns a value but, since you are interested only in the underlying operations it performs, you don't assign its output to a local variable defined in the caller method, for example:
public static void Main(string[] args)
{
// I want to modify the records but I'm not interested
// in knowing how many of them have been modified.
ModifyRecords();
}
public static Int32 ModifyRecords()
{
Int32 affectedRecords = 0;
for (Int32 i = 0; i < s_Records.Count; ++i)
{
Record r = s_Records[i];
if (String.IsNullOrWhiteSpace(r.Name))
{
r.Name = "Default Name";
++affectedRecords;
}
}
return affectedRecords;
}
Actually, I would call it a cosmetic feature... in the sense that it's a design time feature (the computations concerning the discarded variables are performed anyway) that helps keeping the code clear, readable and easy to maintain.
I find the example shown in the link you provided kinda misleading. If I try to parse a String as a Boolean, chances are I want to use the parsed value somewhere in my code. Otherwise I would just try to see if the String corresponds to the text representation of a Boolean (a regular expression, for example... even a simple if statement could do the job if casing is properly handled). I'm far from saying that this never happens or that it's a bad practice, I'm just saying it's not the most common coding pattern you may need to produce.
The example provided in this article, on the opposite, really shows the full potential of this feature:
public static void Main()
{
var (_, _, _, pop1, _, pop2) = QueryCityDataForYears("New York City", 1960, 2010);
Console.WriteLine($"Population change, 1960 to 2010: {pop2 - pop1:N0}");
}
private static (string, double, int, int, int, int) QueryCityDataForYears(string name, int year1, int year2)
{
int population1 = 0, population2 = 0;
double area = 0;
if (name == "New York City")
{
area = 468.48;
if (year1 == 1960) {
population1 = 7781984;
}
if (year2 == 2010) {
population2 = 8175133;
}
return (name, area, year1, population1, year2, population2);
}
return ("", 0, 0, 0, 0, 0);
}
From what I can see reading the above code, it seems that the discards have a higher sinergy with other paradigms introduced in the most recent versions of C# like tuples deconstruction.
For Matlab programmers, discards are far from being a new concept because the programming language implements them since very, very, very long time (probably since the beginning, but I can't say for sure). The official documentation describes them as follows (link here):
Request all three possible outputs from the fileparts function:
helpFile = which('help');
[helpPath,name,ext] = fileparts('C:\Path\data.txt');
The current workspace now contains three variables from fileparts: helpPath, name, and ext. In this case, the variables are small. However, some functions return results that use much more memory. If you do not need those variables, they waste space on your system.
Ignore the first output using a tilde (~):
[~,name,ext] = fileparts(helpFile);
The only difference is that, in Matlab, inner computations for discarded outputs are normally skipped because output arguments are flexible and you can know how many and which one of them have been requested by the caller.

I have seen discards used mainly against methods which return Task<T> but you don't want to await the output.
So in the example below, we don't want to await the output of SomeOtherMethod() so we could do something like this:
//myClass.cs
public async Task<bool> Example() => await SomeOtherMethod()
// example.cs
Example();
Except this will generate the following warning:
CS4014 Because this call is not awaited, execution of the
current method continues before the call is completed. Consider
applying the 'await' operator to the result of the call.
To mitigate this warning and essentially ensure the compiler that we know what we are doing, you can use a discard:
//myClass.cs
public async Task<bool> Example() => await SomeOtherMethod()
// example.cs
_ = Example();
No more warnings.

To add another use case to the above answers.
You can use a discard in conjunction with a null coalescing operator to do a nice one-line null check at the start of your functions:
_ = myParam ?? throw new MyException();

Many times I've done code along these lines:
TextBox.BackColor = int32.TryParse(TextBox.Text, out int32 _) ? Color.LightGreen : Color.Pink;
Note that this would be part of a larger collection of data, not a standalone thing. The idea is to provide immediate feedback on the validity of each field of the data they are entering.
I use light green and pink rather than the green and red one would expect--the latter colors are dark enough that the text becomes a bit hard to read and the meaning of the lighter versions is still totally obvious.
(In some cases I also have a Color.Yellow to flag something which is not valid but neither is it totally invalid. Say the parser will accept fractions and the field currently contains "2 1". That could be part of "2 1/2" so it's not garbage, but neither is it valid.)

Discard pattern can be used with a switch expression as well.
string result = shape switch
{
Rectangule r => $"Rectangule",
Circle c => $"Circle",
_ => "Unknown Shape"
};
For a list of patterns with discards refer to this article: Discards.

Consider this:
5 + 7;
This "statement" performs an evaluation but is not assigned to something. It will be immediately highlighted with the CS error code CS0201.
// Only assignment, call, increment, decrement, and new object expressions can be used as a statement
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/compiler-messages/cs0201?f1url=%3FappId%3Droslyn%26k%3Dk(CS0201)
A discard variable used here will not change the fact that it is an unused expression, rather it will appear to the compiler, to you, and others reviewing your code that it was intentionally unused.
_ = 5 + 7; //acceptable

It can also be used in lambda expressions when having unused parameters:
builder.Services.AddSingleton<ICommandDispatcher>(_ => dispatcher);

Related

Why does a zero-length stackalloc make the C# compiler happy to allow conditional stackallocs?

The following "fix" is very confusing to me; the scenario here is conditionally deciding whether to use the stack vs a leased buffer depending on the size - a pretty niche but sometimes-necessary optimization, however: with the "obvious" implementation (number 3, deferring definite assignment until we actually want to assign it), the compiler complains with CS8353:
A result of a stackalloc expression of type 'Span<int>' cannot be used in this context because it may be exposed outside of the containing method
The short repro (a complete repro follows) is:
// take your pick of:
// Span<int> s = stackalloc[0]; // works
// Span<int> s = default; // fails
// Span<int> s; // fails
if (condition)
{ // CS8353 happens here
s = stackalloc int[size];
}
else
{
s = // some other expression
}
// use s here
The only thing I can think here is that the compiler is really flagging that the stackalloc is escaping the context in which the stackalloc happens, and is waving a flag to say "I can't prove whether this is going to be safe later in the method", but by having the stackalloc[0] at the start, we're pushing the "dangerous" context scope higher, and now the compiler is happy that it never escapes the "dangerous" scope (i.e. it never actually leaves the method, since we're declaring at the top scope). Is this understanding correct, and it is just a compiler limitation in terms of what can be proven?
What's really interesting (to me) is that the = stackalloc[0] is fundamentally a no-op anyway, meaning that at least in the compiled form the working number 1 = stackalloc[0] is identical to the failing number 2 = default.
Full repro (also available on SharpLab to look at the IL).
using System;
using System.Buffers;
public static class C
{
public static void StackAllocFun(int count)
{
// #1 this is legal, just initializes s as a default span
Span<int> s = stackalloc int[0];
// #2 this is illegal: error CS8353: A result of a stackalloc expression
// of type 'Span<int>' cannot be used in this context because it may
// be exposed outside of the containing method
// Span<int> s = default;
// #3 as is this (also illegal, identical error)
// Span<int> s;
int[] oversized = null;
try
{
if (count < 32)
{ // CS8353 happens at this stackalloc
s = stackalloc int[count];
}
else
{
oversized = ArrayPool<int>.Shared.Rent(count);
s = new Span<int>(oversized, 0, count);
}
Populate(s);
DoSomethingWith(s);
}
finally
{
if (oversized is not null)
{
ArrayPool<int>.Shared.Return(oversized);
}
}
}
private static void Populate(Span<int> s)
=> throw new NotImplementedException(); // whatever
private static void DoSomethingWith(ReadOnlySpan<int> s)
=> throw new NotImplementedException(); // whatever
// note: ShowNoOpX and ShowNoOpY compile identically just:
// ldloca.s 0, initobj Span<int>, ldloc.0
static void ShowNoOpX()
{
Span<int> s = stackalloc int[0];
DoSomethingWith(s);
}
static void ShowNoOpY()
{
Span<int> s = default;
DoSomethingWith(s);
}
}
The Span<T> / ref feature is essentially a series of rules about to which scope a given value can escape by value or by reference. While this is written in terms of method scopes it's helpful to simplify to just one of two statements:
The value cannot be returned from the method
The value can be returned from the method
The span safety doc goes into great detail about how the scope is calculated for various statements and expressions. The relevant part here though is for how locals are processed.
The main take away is that whether or not a local can return is calculated at the local declaration time. At the point the local is declared the compiler examines the initializer and makes a decision about whether the local can or cannot be return from the method. In the case there is an initializer then the local will be able to return if the initialization expression is able to be returned.
How do you handle the case where a local is declared but there is no initializer? The compiler has to make a decision: can it or can it not return? When designing the feature we made the decision that the default would be "it can be returned" because it's the decision that caused the least amount of friction for existing patterns.
That did leave us with the problem of how developers could declare a local that wasn't safe to return but also lacked an initializer. Eventually we settled on the pattern of = stackalloc [0]. This is an expression that is safe to optimize away and a strong indicator, basically a requirement, that the local isn't safe to return.
Knowing that this explains the behavior you are seeing:
Span<int> s = stackalloc[0]: this is not safe to return hence the later stackalloc succeeds
Span<int> s = default: this is safe to return because default is safe to return. This means the later stackalloc fails because you're assigning a value that isn't safe to return to a local that is marked as safe to return
Span<int> s;: this is safe to return because that is the default for unininitialized locals. This means the later stackalloc fails because you're assigning a value that isn't safe to return to a local that is marked as safe to return
The real downside to the = stackalloc[0] approach is that it's only applicable to Span<T>. It's not a general solution for ref struct. In practice though it's not as much of a problem for other types. There is some speculation on how we could make it more general but not enough evidence to justify doing it at this point.
Isn't an answer to "why"; however you could change it to a ternary operator slicing the result of the array assignment to a Span:
public static void StackAllocFun(int count)
{
int[] oversized = null;
try
{
Span<int> s = ((uint)count < 32) ?
stackalloc int[count] :
(oversized = ArrayPool<int>.Shared.Rent(count)).AsSpan(0, count);
Populate(s);
DoSomethingWith(s);
}
finally
{
if (oversized is not null)
{
ArrayPool<int>.Shared.Return(oversized);
}
}
}

C# reinterpret bool as byte/int (branch-free)

Is it possible in C# to turn a bool into a byte or int (or any integral type, really) without branching?
In other words, this is not good enough:
var myInt = myBool ? 1 : 0;
We might say we want to reinterpret a bool as the underlying byte, preferably in as few instructions as possible. The purpose is to avoid branch prediction fails as seen here.
unsafe
{
byte myByte = *(byte*)&myBool;
}
Another option is System.Runtime.CompilerServices.Unsafe, which requires a NuGet package on non-Core platforms:
byte myByte = Unsafe.As<bool, byte>(ref myBool);
The CLI specification only defines false as 0 and true as anything except 0 , so technically speaking this might not work as expected on all platforms. However, as far as I know the C# compiler also makes the assumption that there are only two values for bool, so in practice I would expect it to work outside of mostly academic cases.
The usual C# equivalent to "reinterpret cast" is to define a struct with fields of the types you want to reinterpret. That approach works fine in most cases. In your case, that would look like this:
[StructLayout(LayoutKind.Explicit)]
struct BoolByte
{
[FieldOffset(0)]
public bool Bool;
[FieldOffset(0)]
public byte Byte;
}
Then you can do something like this:
BoolByte bb = new BoolByte();
bb.Bool = true;
int myInt = bb.Byte;
Note that you only have to initialize the variable once, then you can set Bool and retrieve Byte as often as you like. This should perform as well or better than any approach involving unsafe code, calling methods, etc., especially with respect to addressing any branch-prediction issues.
It's important to point out that if you can read a bool as a byte, then of course anyone can write a bool as a byte, and the actual int value of the bool when it's true may or may not be 1. It technically could be any non-zero value.
All that said, this will make the code a lot harder to maintain. Both because of the lack of guarantees of what a true value actually looks like, and just because of the added complexity. It would be extremely rare to run into a real-world scenario that suffers from the missed branch-prediction issue you're asking about. Even if you had a legitimate real-world example, it's arguable that it would be better solved some other way. The exact alternative would depend on the specific real-world example, but one example might be to keep the data organized in a way that allows for batch processing on a given condition instead of testing for each element.
I strongly advise against doing something like this, until you have a demonstrated, reproducible real-world problem, and have exhausted other more idiomatic and maintainable options.
Here is a solution that takes more lines (and presumably more instructions) than I would like, but that actually solves the problem directly, i.e. by reinterpreting.
Since .NET Core 2.1, we have some reinterpret methods available in MemoryMarshal. We can treat our bool as a ReadOnlySpan<bool>, which in turn we can treat as a ReadOnlySpan<byte>. From there, it is trivial to read the single byte value.
var myBool = true;
var myBoolSpan = MemoryMarshal.CreateReadOnlySpan(ref myBool, length: 1);
var myByteSpan = MemoryMarshal.AsBytes(myBoolSpan);
var myByte = myByteSpan[0]; // =1
maybe this would work? (source of the idea)
using System;
using System.Reflection.Emit;
namespace ConsoleApp10
{
class Program
{
static Func<bool, int> BoolToInt;
static Func<bool, byte> BoolToByte;
static void Main(string[] args)
{
InitIL();
Console.WriteLine(BoolToInt(true));
Console.WriteLine(BoolToInt(false));
Console.WriteLine(BoolToByte(true));
Console.WriteLine(BoolToByte(false));
Console.ReadLine();
}
static void InitIL()
{
var methodBoolToInt = new DynamicMethod("BoolToInt", typeof(int), new Type[] { typeof(bool) });
var ilBoolToInt = methodBoolToInt.GetILGenerator();
ilBoolToInt.Emit(OpCodes.Ldarg_0);
ilBoolToInt.Emit(OpCodes.Ldc_I4_0); //these 2 lines
ilBoolToInt.Emit(OpCodes.Cgt_Un); //might not be needed
ilBoolToInt.Emit(OpCodes.Ret);
BoolToInt = (Func<bool, int>)methodBoolToInt.CreateDelegate(typeof(Func<bool, int>));
var methodBoolToByte = new DynamicMethod("BoolToByte", typeof(byte), new Type[] { typeof(bool) });
var ilBoolToByte = methodBoolToByte.GetILGenerator();
ilBoolToByte.Emit(OpCodes.Ldarg_0);
ilBoolToByte.Emit(OpCodes.Ldc_I4_0); //these 2 lines
ilBoolToByte.Emit(OpCodes.Cgt_Un); //might not be needed
ilBoolToByte.Emit(OpCodes.Ret);
BoolToByte = (Func<bool, byte>)methodBoolToByte.CreateDelegate(typeof(Func<bool, byte>));
}
}
}
based on microsoft documentation of each emit.
load the parameter in memory (the boolean)
load in memory a value of int = 0
compare if any the parameter is greater than the value (branching here maybe?)
return 1 if true else 0
line 2 and 3 can be removed but the return value could be something else than 0 / 1
like i said in the beginning this code is taken from another response, this seem to be working yes but it seem slow while being benchmarking, lookup .net DynamicMethod slow to find way to make it "faster"
you could maybe use the .GetHashCode of the boolean?
true will return int of 1 and false 0
you can then var myByte = (byte)bool.GetHashCode();

What's the correct way to implement operator ++ for value-types?

I'm working on a custom implementation of a Number struct, with very different ways of storing and manipulating numeric values.
The struct is fully immutable - all fields are implemented as readonly
I'm trying to implement the ++ and -- operators, and I've run into a little confusion:
How do you perform the assignment?
Or does the platform handle this automatically, and I just need to return n + 1?
public struct Number
{
// ...
// ... readonly fields and properties ...
// ... other implementations ...
// ...
// Empty placeholder + operator, since the actual method of addition is not important.
public static Number operator +(Number n, int value)
{
// Perform addition and return sum
// The Number struct is immutable, so this technically returns a new Number value.
}
// ERROR here: "ref and out are not valid in this context"
public static Number operator ++(ref Number n)
{
// ref seems to be required,
// otherwise this assignment doesn't affect the original variable?
n = n + 1;
return n;
}
}
EDIT: I think this is not a duplicate of other questions about increment and decrement operators, since this involves value-types which behave differently than classes in this context. I understand similar rules apply regarding ++ and --, but I believe the context of this question is different enough, and nuanced enough, to stand on its own.
The struct is fully immutable - all fields are implemented as readonly
Good!
I'm trying to implement the ++ and -- operators, and I've run into a little confusion: How do you perform the assignment?
You don't. Remember what the ++ operator does. Whether it is prefix or postfix it:
fetches the original value of the operand
computes the value of the successor
stores the successor
produces either the original value or the successor
The only part of that process that the C# compiler does not know how to do for your type is "compute the successor", so that's what your overridden ++ operator should do. Just return the successor; let the compiler deal with figuring out how to make the assignment.
Or does the platform handle this automatically, and I just need to return n + 1?
Yes, do that.
The processing of ++ and -- operators is described in C# language specification, section 7.7.5 Prefix increment and decrement operators:
The run-time processing of a prefix increment or decrement operation of the form ++x or --x consists of the following steps:
• If x is classified as a variable:
  o x is evaluated to produce the variable.
  o The selected operator is invoked with the value of x as its argument.
  o The value returned by the operator is stored in the location given by the evaluation of x.
  o The value returned by the operator becomes the result of the operation.
So a custom overloads of these operators only need to produce an incremented/decremented value. The rest is handled by the compiler.
A Number class is going to have a value of some kind as a property.
public static Number operator ++(Number n)
{
// ref seems to be required,
// otherwise this assignment doesn't affect the original variable?
n.value = n.value + 1;
return n;
}
This should do what you want.
I wrote this using your struc and added the value property.
private static void Main(string[] args)
{
var x = new Number();
x.value = 3;
x++;
Console.WriteLine(x.value);
Console.Read();
}
This properly generates a 4
The statement num++; by itself expands to num = PlusPlusOperator(num);. Since your data type is immutable, just return n+1; and the compiler will handle the rest.

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;

Which one is better to use and why in c#

Which one is better to use?
int xyz = 0;
OR
int xyz= default(int);
int xyz = 0;
Why make people think more than necessary? default is useful with generic code, but here it doesn't add anything. You should also think if you're initializing it in the right place, with a meaningful value. Sometimes you see, with stack variables, code like:
int xyz = 0;
if(someCondition)
{
// ...
xyz = 1;
// ...
}
else
{
// ...
xyz = 2;
// ...
}
In such cases, you should delay initialization until you have the real value. Do:
int xyz;
if(someCondition)
{
// ...
xyz = 1;
// ...
}
else
{
// ...
xyz = 2;
// ...
}
The compiler ensures you don't use an uninitialized stack variable. In some cases, you have to use meaningless values because the compiler can't know code will never execute (due to an exception, call to Exit, etc.). This is the exception (no pun intended) to the rule.
It depends what you want to achieve.
I would prefer
int xyz = 0;
as I believe it is more readable and not confusing.
default keyword is mostly suitable for Generics.
The purpose of the default operator is to provide you with the default value for a type, but it was added primarily to allow generics to have a valid value for values declared to be of its generic type arguments.
I don't have hard evidence but I suspect the compiler will emit the same code for both in your specific case.
However, here there is a legitimate use of default:
public T Aggregate<T>(IEnumerable<T> collection, Func<T, T, T> aggregation)
{
T result = default(T);
foreach (T element in collection)
result = aggregation(result, element);
return result;
}
Without default, the above code would need some hacks in order to compile and function properly.
So use the first, set it to 0.
no performance difference between your codes. to see clearly use int xyz = 0;
Given that the emitted CIL is identical (you get
IL_0001: ldc.i4.0
IL_0002: stloc.0
in both cases), the rule is to choose the one you feel better communicates the intent of the code. Normally, questions of feeling are subjective and hard-to-decide; in this case, however, were I the code reviewer, I would have to be presented with an extremely compelling reason to accept what looks at first sight to be an entirely superfluous use of default().
int xyz = default(int);
I like this way when working with Generics bcoz it give you flexibility to get default of whatever type you are working with.
int xyz=0;
On the other hand this is easy and fast and obviously won't work in generic cases.
Both have their pros and cons..
Regards,
int xyz = 0 is moreclear, defaut is generally used with generics
the best is
int xyz;
because you can't access to uninitialized variable.

Categories

Resources