📜 ⬆️ ⬇️

C # Tricks

IMHO, instead of twisting the interlocutors' brains about the abstruse semantics of event and delegates or asking when writing new IEntity() legal, you can ask a simpler question - for example, “give an example of unusual behavior or use of the C # language”. Here are some examples that came to mind as possible answers.




Operators | and & against || and &&


Both pairs of statements can be applied to bool variables. The only difference is that single operators do not reduce the number of calculations if the result is obvious:



bool b = false && a(); // a() not called
bool c = false & a(); // a() called

Pass null as exception


Oddly enough, passing null as an exception causes a NullReferenceException to be NullReferenceException :


')
try {
throw null ;
} catch (NullReferenceException) {
// will be caught!
}

Strange arrow when listing


It can be a good idea to bother your colleagues if instead of the typical for for when counting, use while with an unusual arrow. The syntax is absolutely legal! By the way - I remember here on Habré someone embarrassed ...



public IEnumerable<Foo> Create( int count)
{
while (count --> 0)
yield return new Foo();
}

Useful operator ??


Can I use the operator ?? for lazy object initialization:



private IList<Person> people;
public IList<Person> People {
get {
return people ??
(people = new List<Person>());
}
}

You can also use an operator to check chains of values:



int err( int ? alpha, int ? beta)
{
return alpha ?? beta ?? -1;
}

Although IMHO for laziness is suitable and AOR. Or Boo :)



Extension methods


Extension methods can be applied not only to specific types but also to interfaces. This allows classes to add behavior without wedging into their inheritance hierarchy:



public static void T DeepCopy<T>
( this ICopyable<T> self)
where T : class , new ()
{
â‹®
}
}

In principle, extensions to interfaces are “behavioral impurities” (behavior mixing). Unlike F #, you can't mix in properties, although if you really wanted to (warning: recommended ), you can write something like this:



static class ExtensionMethods
{
private static Dictionary<WeakReference, object > tags =
new Dictionary<WeakReference, object >();
public static void SetTag( this object obj, object tagValue)
{
Cleanup();
var found = tags.Select(o => o.Key)
.Where(k => ReferenceEquals(obj, k.Target));
if (found.Count() > 0)
{
tags[found.Single()] = tagValue;
}
else
tags[ new WeakReference(obj)] = tagValue;
}
public static T GetTag<T>( this object obj)
{
return (T)tags.Where(o => ReferenceEquals(o.Key.Target, obj)).First().Value;
}
private static void Cleanup()
{
var toRemove = tags.Select(o => o.Key).Where(p => !p.IsAlive);
foreach ( var tr in toRemove)
tags.Remove(tr);
}
}

Lambda instead of strings


Sometimes you need to keep the variable name in a string literal. Instead of using a literal directly, you can pass a delegate to a function and pull out the string when parsing the expression. (This makes the code more secure and makes refactoring easier.)



public static string PropertyName<T>
( this object obj, Expression<Func<T>> p)
{
return (p.Body as MemberExpression).Member.Name;
}

You can use this design as follows:



lblName.DataBindings.Add(
PropertyName(() => Name), this , null );

Similar manipulations are possible with methods. And indeed with anything :)



Return value from try-finally


It is possible to do boldly from the try-finally block. At the same time, the compiler caches the return value, and it will be returned only after the execution of the finally block.



try {
a();
return x; // cached
}
finally {
b(); // called before x is returned
}

Creative use Dispose ()


The IDisposable interface can be used to create blocks, the input and output to which you want to intercept. For example, change the cursor to the time of the operation:



class WaitCursor : IDisposable {
private Cursor oldCursor;
public WaitCursor(Cursor oldCursor) {
this .oldCursor = oldCursor;
SetCursor(Cursor.Wait);
}
public void Dispose() {
SetCursor(oldCursor);
}
}

You can use this construct as follows:



using ( new WaitCursor( this .Cursor))
{
// long operation
}

Although for such constructs you can also use AOR.



Stub Delegate


In order not to check the event for null, you can sign a delegate stub when declaring:
public event MyClickHandler Click = delegate {};

Finally


The fact that employers are straining their interlocutors with all sorts of delusional tasks like “isolated case” is certainly very good :) because it becomes easier for us to compete with them for cool developers.



Criticism welcome!

Source: https://habr.com/ru/post/67991/


All Articles