questions - stackoverflow c#




Versteckte Funktionen von C#? (20)

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

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


Von CLR über C # :

Bei der Normalisierung von Zeichenfolgen wird dringend empfohlen, ToUpperInvariant anstelle von ToLowerInvariant zu verwenden, da Microsoft den Code für die Durchführung von Vergleichen in Großbuchstaben optimiert hat .

Ich erinnere mich, dass mein Kollege die Zeichenfolgen vor dem Vergleich immer in Großbuchstaben umwandelte. Ich habe mich immer gefragt, warum er das macht, weil ich es eher "natürlich" finde, zuerst in Kleinbuchstaben zu konvertieren. Nachdem ich jetzt das Buch gelesen habe, weiß ich warum.


  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

" 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: ?? ??


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

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


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;

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


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

Von Rick Strahl :

Sie können die Kette? Operator, so dass Sie eine Reihe von Null-Vergleichen durchführen können.

string result = value1 ?? value2 ?? value3 ?? String.Empty;

Zwei Dinge, die ich mag, sind automatische Eigenschaften, so dass Sie Ihren Code noch weiter reduzieren können:

private string _name;
public string Name
{
    get
    {
        return _name;
    }
    set
    {
        _name = value;
    }
}

wird

public string Name { get; set;}

Auch Objektinitialisierer:

Employee emp = new Employee();
emp.Name = "John Smith";
emp.StartDate = DateTime.Now();

wird

Employee emp = new Employee {Name="John Smith", StartDate=DateTime.Now()}

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;


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


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

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;

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

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.





hidden-features