Florian Rappl, MVP Visual C#
WinForms, WPF, Azure
HTML5, ASP.NET MVC
Intel MIC, OMP, MPI
Expression
)
Func<double, double> g = delegate (double x) { return x * x; };
Func<double, double> f = x => x * x;
switch
statementDictionary
gives us more flexibility:
var functions = new Dictionary<string, Func<double, double>>();
void Init() {
functions.Add("sin", Math.Sin);
functions.Add("cos", Math.Cos); /* and others */
}
public double Evaluate(string f, double x) {
//Let's just assume that the specified function exists
return functions[f](x);
}
SynchronizationContext
var ctx = SynchronizationContext.Current ?? new SynchronizationContext();
public event EventHandler<MyEventArgs> Event;
public void RaiseEvent() {
if(Event != null)
ctx.Post(o => Event(this, new MyEventArgs(a1, ..., an)), null);
}
null
) required
class Greeter {
public Greeter() {
SayHello = () => {
SayHello = () => {
SayHello = () => {
return "Stop it for God's sake!"
};
return "I already said hello!";
};
return "Hello";
};
}
public Func<string> SayHello { get; private set; }
}
Task
async
/ await
// A usual (non-async) method
int ComputeNumber() {
return 42;
}
// Decorate method as being async - will be wrapped automatically
async Task<int> ComputeNumberAsync() {
return 42;
}
// Can be used as always
var answer = ComputeNumberAsync().Result;
// Or with await
var answer = await ComputeNumberAsync();
// Important: No new thread or similar has been created previously
var answer = await Task.Run(ComputeNumber);
// Auto-wrapping by using async is required for await
async Task ComputeNumberAsync() {
/* Do some UI changes (in UI / current thread) */
var result = await LongRunningTask();
/* Do some UI changes (back in UI / current thread) */
}
async
Methods if availableTask
or Task<T>
void
in case of event handlersTask.Run
in case of memory bound methodsConfigureAwait(false)
for creating APIsTaskCompletionSource
// Creating extension methods like this
public static async Task WhenClicked(this Button button) {
var tcs = new TaskCompletionSource<bool>();
RoutedEventHandler ev = (sender, evt) => tcs.TrySetResult(true);
//This is a perfect async. code, no other thread required
try {
button.Click += ev;
await tcs.Task;
} finally {
button.Click -= ev;
}
}
// Using them
await button.WhenClicked();
Dictionary
, ConcurrentDictionary
, etc.)
public class Logger {
public static void WriteLine(string s) { /*...*/ }
}
public class BoxingExample {
public void Log(int id, int size) {
var s = string.Format("{0}:{1}", id, size);
Logger.WriteLine(s);
}
}
Compiler selects string.Format(string, object, object)
.
public class BoxingExample {
public void Log(int id, int size) {
var s = string.Format("{0}:{1}", id.ToString(), size.ToString());
Logger.WriteLine(s);
}
}
public class Logger {
public static void WriteLine(string s) { /*...*/ }
}
public class BoxingExample {
public void Log(int id, int size) {
var s = id.ToString() + ':' + size.ToString();
Logger.WriteLine(s);
}
}
Compiled to string.Concat(object, object, object)
.
public class BoxingExample {
public void Log(int id, int size) {
var s = id.ToString() + ":" + size.ToString();
Logger.WriteLine(s);
}
}
public enum Color {
Red, Green, Blue
}
public class BoxingExample {
string name;
Color color;
public override int GetHashCode() {
return name.GetHashCode() ^ color.GetHashCode();
}
}
The enum value is boxed - use (int)color
before calling GetHashCode
.
class Symbol {
public string Name { get; private set; }
/*...*/
}
class Compiler {
List<Symbol> symbols;
public Symbol FindMatchingSymbol(string name) {
return symbols.FirstOrDefault(s => s.Name == name);
}
}
class Compiler {
List<Symbol> symbols;
public Symbol FindMatchingSymbol(string name) {
Func<Symbol, bool> predicate = s => s.Name == name;
IEnumerable<Symbol> enumerable = symbols;
IEnumerator<Symbol> enumerator = enumerable.GetEnumerator();
while(enumerator.MoveNext()) {
if (predicate(enumerator.Current))
return enumerator.Current;
}
return default(Symbol);
}
}
class Compiler {
List<Symbol> symbols;
public Symbol FindMatchingSymbol(string name) {
foreach (Symbol s in symbols) {
if (s.Name == name)
return s;
}
return null;
}
}
StringBuilder
instances are unnecessaryStringBuilder
struct
string[] lines = text.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None);
int numLines = lines.Length; bool skipSpace = true;
if (lines[0].TrimStart().StartsWith("///")) {
for (int i = 0; i < numLines; i++) {
string trimmed = lines[i].TrimStart();
if (trimmed.Length < 4 || !char.IsWhiteSpace(trimmed[3])) {
skipSpace = false;
break;
}
}
int substringStart = skipSpace ? 4 : 3;
for (int i = 0; i < numLines; i++)
WriteLine(lines[i].TrimStart().Substring(substringStart));
} else { /* ... */ }
int IndexOfFirstNonWhiteSpaceChar(string text, int start) {
while (start < text.Length && char.IsWhiteSpace(text[start]))
start++;
return start;
}
bool TrimmedStringStartsWith(string text, int start, string prefix) {
start = IndexOfFirstNonWhiteSpaceChar(text, start);
int len = text.Length - start;
if (len < prefix.Length) return false;
for (int i = 0; i < len; i++) {
if (prefix[i] != text[start + i]) return false;
}
return true;
}
// etc...
List<string>
is faster than StringCollection
BitmapImage m_bmp;
protected override async void OnNavigatedTo(NavigationEventArgs e) {
base.OnNavigatedTo(e);
await PlayIntroSoundAsync();
image1.Source = m_bmp;
Canvas.SetLeft(image1, Window.Current.Bounds.Width - m_bmp.PixelWidth);
}
protected override async void LoadState(Object nav, Dictionary<String, Object> pageState) {
m_bmp = new BitmapImage();
var file = await StorageFile.GetFileFromApplicationUriAsync("...");
using (var stream = await file.OpenReadAsync())
await m_bmp.SetSourceAsync(stream);
}
Task<BitmapImage> m_bmpTask;
protected override async void OnNavigatedTo(NavigationEventArgs e) {
base.OnNavigatedTo(e);
await PlayIntroSoundAsync();
var bmp = await m_bmpTask;
image1.Source = bmp;
Canvas.SetLeft(image1, Window.Current.Bounds.Width - bmp.PixelWidth);
}
protected override void LoadState(/* ... */) {
m_bmpTask = LoadBitmapAsync();
}
async Task<BitmapImage> LoadBitmapAsync() {
var bmp = new BitmapImage(); /* ... */ return bmp;
}
try {
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
{
await LoadAsync();
m_Result = "done";
throw new Exception();
});
} catch (Exception) {
/* will not be entered */
} finally {
DebugPrint(m_Result);
}
LoadAsync
is invokedasync
overload
[StructLayout(LayoutKind.Explicit, Pack = 1)]
struct Number {
[FieldOffset(0)]
public int Value;
[FieldOffset(0)]
public byte First;
[FieldOffset(1)]
public byte Second;
[FieldOffset(2)]
public byte Third;
[FieldOffset(3)]
public byte Fourth;
}
abstract class Mother {
public abstract void DoSomething();
}
class Daughter {
public sealed override void DoSomething() { }
}
callvirt
instead of call
WeakReference
)
WeakEvent<EventHandler> _event = new WeakEvent<EventHandler>();
//Let public event appear normally
public event EventHandler Event {
add { _event.Add(value); }
remove { _event.Remove(value); }
}
//Fire over a special method (good practice anyway)
public void RaiseEvent() {
_event.Raise(this, EventArgs.Empty);
}
//Using it is straight forward:
someClassInstance.Event += MyEventHandler;
readonly
should be preferredconst
has the advantage of allowing switch
readonly
: Changes affect external codePI
as a constant is valid
[Flags]
enum MyBitFlag { /* ... */ }
[DebuggerStepThrough]
void MyShortHelper() { /* ... */ }
[Conditional("DEBUG")]
void MyDebuggingHelper() { /* ... */ }
[DebuggerDisplay("FirstName={FirstName}, LastName={LastName}")]
class MyClass { /* ... */ }
[ThreadStatic]
static StringBuilder cachedStringBuilder;
CallerMemberName
attributeExpression
static string GetName([CallerMemberName] string name = null) {
return name ?? string.Empty;
}
Contact me any time ...