hidden-features operator - Versteckte Funktionen von C#?




stackoverflow newest (25)

Das kam mir in den Sinn, nachdem ich aus dieser Frage folgendes gelernt hatte:

where T : struct

Wir, C # -Entwickler, kennen die Grundlagen von C #. Ich meine Deklarationen, Bedingungen, Schleifen, Operatoren usw.

Einige von uns beherrschen sogar die Sachen wie Generics , anonyme Typen , lambdas , LINQ , ...

Aber was sind die verborgensten Features oder Tricks von C #, die selbst C # -Fans, Süchtige, Experten kaum kennen?

Hier sind die bisher offenbarten Features:


Schlüsselwörter

Attribute

Syntax

Sprachmerkmale

Visual Studio-Funktionen

Rahmen

Methoden und Eigenschaften

  • String.IsNullOrEmpty() -Methode von KiwiBastard
  • List.ForEach() -Methode von KiwiBastard
  • BeginInvoke() , EndInvoke() Methoden von Will Dean
  • Nullable<T>.HasValue und Nullable<T>.Value Eigenschaften von Rismo
  • GetValueOrDefault Methode von John Sheehan

Tipps

  • Nette Methode für Eventhandler von Andreas HR Nilsson
  • Großvergleiche von John
  • Greife auf anonyme Typen ohne Reflektion von dp
  • Ein schneller Weg, um die Auflistungseigenschaften von Will instanziieren zu können
  • JavaScript-ähnliche anonyme Inline-Funktionen von roosteronacid

Andere


Answers

Not sure why anyone would ever want to use Nullable<bool> though. :-)

True, False, FileNotFound ?


Aliase Generics:

using ASimpleName = Dictionary<string, Dictionary<string, List<string>>>;

Sie können ASimpleName statt Dictionary<string, Dictionary<string, List<string>>> .

Verwenden Sie es, wenn Sie an vielen Orten die gleiche generische große lange komplexe Sache verwenden würden.


Mein Lieblingstrick ist die Verwendung des Null-Coalesce-Operators und Klammern, um Sammlungen automatisch für mich zu instanziieren.

private IList<Foo> _foo;

public IList<Foo> ListOfFoo 
    { get { return _foo ?? (_foo = new List<Foo>()); } }

Unions (C ++ Shared Memory Art) in reinem, sicherem C #

Ohne auf unsicheren Modus und Zeiger zurückgreifen zu müssen, können Sie Klassenmitgliedern Speicherplatz in einer Klasse / Struktur freigeben. Angesichts der folgenden Klasse:

[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;
}

Sie können die Werte der Bytefelder ändern, indem Sie das Feld Int32 und umgekehrt bearbeiten. Zum Beispiel, dieses Programm:

    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);
    }

Gibt Folgendes aus:

2147483647
FF FF FF 7F
65535

Fügen Sie einfach mit System.Runtime.InteropServices hinzu;


Das ist nicht C # per se, aber ich habe niemanden gesehen, der System.IO.Path.Combine() in dem Maße verwendet, wie es sein sollte. In der Tat ist die gesamte Path-Klasse wirklich nützlich, aber niemand benutzt sie!

Ich wette, dass jede Produktions-App den folgenden Code hat, obwohl es nicht sollte:

string path = dir + "\\" + fileName;

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;
}

Ich finde, dass die meisten C # -Entwickler nicht über "Nullable" -Typen Bescheid wissen. Im Grunde Grundelemente, die einen Nullwert haben können.

double? num1 = null; 
double num2 = num1 ?? -100;

Setzen Sie ein Nullable-Double, num1 , auf null und legen Sie dann ein reguläres double, num2 , auf num1 oder -100 fest, wenn num1 null war.

http://msdn.microsoft.com/en-us/library/1t3y8s4s(VS.80).aspx

eine weitere Sache über Nullable Typ:

DateTime? tmp = new DateTime();
tmp = null;
return tmp.ToString();

es ist return String.Empty. Überprüfen Sie this Link für weitere Details


lambdas und type inferrence werden unterschätzt. Lambdas können mehrere Anweisungen haben und sie können automatisch als kompatibles Delegate-Objekt fungieren (stellen Sie einfach sicher, dass die Signatur übereinstimmt) wie in:

Console.CancelKeyPress +=
    (sender, e) => {
        Console.WriteLine("CTRL+C detected!\n");
        e.Cancel = true;
    };

Beachten Sie, dass ich weder einen new CancellationEventHandler noch muss ich die sender und e Typen angeben, die aus dem Event stammen. Deshalb ist es weniger umständlich, den ganzen delegate (blah blah) zu schreiben delegate (blah blah) was auch erfordert, dass Sie Arten von Parametern angeben.

Lambdas müssen nichts zurückgeben, und Inferenz ist im Kontext so extrem mächtig.

Und BTW, Sie können immer Lambdas zurückgeben, die Lambdas im Sinne der funktionalen Programmierung machen. Zum Beispiel ist hier ein Lambda, das ein Lambda erstellt, das ein Button.Click-Ereignis behandelt:

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);

Beachten Sie die Verkettung: (dx, dy) => (sender, e) =>

Jetzt bin ich froh, dass ich die funktionale Programmierklasse genommen habe :-)

Abgesehen von den Zeigern in C, denke ich, es ist die andere grundlegende Sache, die du lernen solltest :-)


Wenn Sie Ihr Programm beenden wollen, ohne irgendwelche finally Blocks oder Finalizer FailFast , verwenden Sie FailFast :

Environment.FailFast()

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.


Hier sind einige interessante versteckte C # -Features in Form von undokumentierten C # -Schlüsselwörtern:

__makeref

__reftype

__refvalue

__arglist

Dies sind undokumentierte C # -Schlüsselwörter (selbst Visual Studio erkennt sie!), Die für ein effizienteres Boxing / Unboxing vor Generics hinzugefügt wurden. Sie arbeiten in Koordination mit der System.TypedReference-Struktur.

Es gibt auch __arglist, die für Parameterlisten mit variabler Länge verwendet wird.

Eine Sache, über die Leute nicht viel wissen, ist System.WeakReference - eine sehr nützliche Klasse, die ein Objekt verfolgt, es aber dem Müllsammler immer noch erlaubt, es zu sammeln.

Das nützlichste "versteckte" Feature wäre das yield return keyword. Es ist nicht wirklich versteckt, aber viele Leute wissen es nicht. LINQ ist darauf aufgebaut; Es ermöglicht verzögerte Abfragen, indem eine Zustandsmaschine unter der Haube erzeugt wird. Raymond Chen hat kürzlich über die internen, düsteren Details geschrieben .


Ich kannte das "as" Keyword schon lange nicht mehr.

MyClass myObject = (MyClass) obj;

vs

MyClass myObject = obj as MyClass;

Die zweite gibt null zurück, wenn obj keine MyClass ist, statt eine Cast-Ausnahme zu werfen.


Verwenden von @ für Variablennamen, bei denen es sich um Schlüsselwörter handelt.

var @object = new object();
var @string = "";
var @if = IpsoFacto(); 

Attribute im Allgemeinen, aber vor allem DebuggerDisplay . Spart Ihnen Jahre.


Alles andere, plus

1) implizite Generika (warum nur für Methoden und nicht für Klassen?)

void GenericMethod<T>( T input ) { ... }

//Infer type, so
GenericMethod<int>(23); //You don't need the <>.
GenericMethod(23);      //Is enough.

2) einfache Lambdas mit einem Parameter:

x => x.ToString() //simplify so many calls

3) anonyme Typen und Initialisierer:

//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 };

Noch einer:

4) Auto-Eigenschaften können unterschiedliche Bereiche haben:

public int MyId { get; private set; }

Danke @pzycoman für die Erinnerung an mich:

5) Namespace-Aliase (nicht dass Sie diese besondere Unterscheidung benötigen):

using web = System.Web.UI.WebControls;
using win = System.Windows.Forms;

web::Control aWebControl = new web::Control();
win::Control aFormControl = new win::Control();

@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.


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"

Das @ weist den Compiler an, alle Escape-Zeichen in einer Zeichenfolge zu ignorieren.

Wollte nur diesen einen klarstellen ... es sagt ihm nicht, die Escape-Zeichen zu ignorieren, es teilt dem Compiler tatsächlich mit, die Zeichenfolge als ein Literal zu interpretieren.

Wenn Sie haben

string s = @"cat
             dog
             fish"

es wird tatsächlich als ausgedruckt (beachten Sie, dass es sogar den Leerraum enthält, der für den Einzug verwendet wird):

cat
             dog
             fish

Vermeiden Sie die Suche nach Null-Event-Handlern

Hinzufügen eines leeren Delegaten zu Ereignissen bei der Deklaration, wodurch die Notwendigkeit unterdrückt wird, das Ereignis immer auf Null zu überprüfen, bevor es aufgerufen wird, ist großartig. Beispiel:

public delegate void MyClickHandler(object sender, string myValue);
public event MyClickHandler Click = delegate {}; // add empty delegate!

Lass es dich tun

public void DoSomething()
{
    Click(this, "foo");
}

An Stelle von

public void DoSomething()
{
    // Unnecessary!
    MyClickHandler click = Click;
    if (click != null) // Unnecessary! 
    {
        click(this, "foo");
    }
}

Bitte beachten Sie auch diese Diskussion und diesen Blogbeitrag von Eric Lippert zu diesem Thema (und mögliche Nachteile).


" yield " würde mir in den Sinn kommen. Einige der Attribute wie DefaultValueAttribute gehören auch zu meinen Favoriten.

Das Schlüsselwort " var " ist ein wenig bekannter, aber Sie können es auch in .NET 2.0-Anwendungen verwenden (solange Sie den .NET 3.5-Compiler verwenden und für die Ausgabe von 2.0-Code festlegen) scheint nicht sehr bekannt zu sein Gut.

Edit: kokos, danke für das Aufzeigen der ?? Betreiber, das ist in der Tat wirklich nützlich. Da es ein bisschen schwierig ist, danach zu googeln (da ?? einfach ignoriert wird), hier ist die MSDN-Dokumentationsseite für diesen Operator: ?? ??


Das Schlüsselwort 'default' in generischen Typen:

T t = default(T);

führt zu einem 'Null', wenn T ein Referenztyp ist, und 0, wenn es ein Int ist, Falsch, wenn es ein Boolescher Wert ist, und so weiter.


Environment.NewLine

for system independent newlines.


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.


  1. ?? - coalescing operator
  2. using ( statement / directive ) - great keyword that can be used for more than just calling Dispose
  3. readonly - should be used more
  4. netmodules - too bad there's no support in Visual Studio

Hierbei werden Ganzzahlen oder Zeichenfolgen in einer Ziel-Enumeration mit teilweiser Übereinstimmung in dot.NET 4.0 mit Generics wie in der oben genannten Tawani-Utility-Klasse analysiert. Ich verwende es, um Befehlszeilenschaltervariablen zu konvertieren, die möglicherweise unvollständig sind. Da eine Aufzählung nicht null sein kann, sollten Sie logisch einen Standardwert angeben. Es kann so aufgerufen werden:

var result = EnumParser<MyEnum>.Parse(valueToParse, MyEnum.FirstValue);

Hier ist der Code:

using System;

public class EnumParser<T> where T : struct
{
    public static T Parse(int toParse, T defaultVal)
    {
        return Parse(toParse + "", defaultVal);
    }
    public static T Parse(string toParse, T defaultVal) 
    {
        T enumVal = defaultVal;
        if (defaultVal is Enum && !String.IsNullOrEmpty(toParse))
        {
            int index;
            if (int.TryParse(toParse, out index))
            {
                Enum.TryParse(index + "", out enumVal);
            }
            else
            {
                if (!Enum.TryParse<T>(toParse + "", true, out enumVal))
                {
                    MatchPartialName(toParse, ref enumVal);
                }
            }
        }
        return enumVal;
    }

    public static void MatchPartialName(string toParse, ref T enumVal)
    {
        foreach (string member in enumVal.GetType().GetEnumNames())
        {
            if (member.ToLower().Contains(toParse.ToLower()))
            {
                if (Enum.TryParse<T>(member + "", out enumVal))
                {
                    break;
                }
            }
        }
    }
}

Zu Ihrer Information : Die Frage war nach ganzen Zahlen, die niemand erwähnt hat, auch explizit in Enum konvertieren.TryParse ()





c# hidden-features