Скрытые возможности C #? [закрыто]

Object.keys () Метод Object.keys () возвращает массив собственных перечислимых свойств данного объекта в том же порядке, что и для цикла for ... in (разница заключается в том, что for-in loop также перечисляет свойства в цепочке прототипов).

var arr1 = Object.keys(obj);

Object.values ​​() Метод Object.values ​​() возвращает массив собственных значений перечислимого свойства данного объекта в том же порядке, что и что обеспечивается циклом for for ... in (разница заключается в том, что цикл for-in также перечисляет свойства в цепочке прототипов).

var arr2 = Object.values(obj);

Для получения дополнительной информации см. здесь

1476
задан 56 revs, 31 users 10% 25 September 2017 в 20:53
поделиться

295 ответов

Также имеется атрибут ThreadStaticAttribute, который делает статическое поле уникальным для каждого потока, поэтому вы можете иметь строго типизированное локальное хранилище для потоков.

Даже если методы расширения не такие уж секретные (LINQ основан на них), может быть не так очевидно, насколько они полезны и более читабельны для вспомогательных методов:

//for adding multiple elements to a collection that doesn't have AddRange
//e.g., collection.Add(item1, item2, itemN);
static void Add<T>(this ICollection<T> coll, params T[] items)
 { foreach (var item in items) coll.Add(item);
 }

//like string.Format() but with custom string representation of arguments
//e.g., "{0} {1} {2}".Format<Custom>(c=>c.Name,"string",new object(),new Custom())
//      result: "string {System.Object} Custom1Name"
static string Format<T>(this string format, Func<T,object> select, params object[] args)
 { for(int i=0; i < args.Length; ++i)
    { var x = args[i] as T;
      if (x != null) args[i] = select(x);
    }
   return string.Format(format, args);
 }
27
ответ дан Mark Cidade 25 September 2017 в 20:53
поделиться

Инициализация поля по требованию в одну строку:

public StringBuilder Builder
{
    get { return _builder ?? (_builder = new StringBuilder()); }
}

Я не уверен, что я думаю о выражениях присваивания, поддерживающих C #, но, эй, это так: -)

27
ответ дан 2 revs 25 September 2017 в 20:53
поделиться

Можно использовать любой символ Unicode на имена C#, например:

public class MyClass
{
    public string Hårføner()
    {
        return "Yes, it works!";
    }
}

можно даже использовать Escape Unicode. Этот эквивалентен вышеупомянутому:

public class MyClass
{
    public string H\u00e5rføner()
    {
        return "Yes, it (still) works!";
    }
}
15
ответ дан 2 revs, 2 users 91% 25 September 2017 в 20:53
поделиться

Исходя из того, что этот поток должен называться « вещей, которые вы не знали о C # до недавнего времени, несмотря на то, что думали, что вы уже знали все », моя личная особенность - асинхронные делегаты.

Пока я не прочитал книгу Джеффа Рихтера по C # / CLR (отличная книга, все, кто занимается .NET, должны ее прочитать), я не знал, что вы можете вызвать любого делегата, используя BeginInvoke / EndInvoke. Я склонен делать много вызовов ThreadPool.QueueUserWorkItem (что, по-моему, очень похоже на то, что делает делегат BeginInvoke внутри страны), но иногда может быть действительно полезным добавление стандартизированного шаблона соединения / сближения.

21
ответ дан 2 revs, 2 users 86% 25 September 2017 в 20:53
поделиться

верный и ложь операторы являются действительно странными.

более всесторонний пример может быть найден здесь .

Редактирование: Там связан ТАК вопрос What’s ложный оператор в пользе C# для?

24
ответ дан 3 revs 25 September 2017 в 20:53
поделиться

Нужно вернуть пустой IEnumerable?

public IEnumerable<T> GetEnumerator(){
  yield break;
}
17
ответ дан Will 25 September 2017 в 20:53
поделиться

Частичные методы

Чарли Калверт объясняет частичные методы в своем блоге

У Скотта Кейта есть хорошая частичная демонстрация метода здесь

  1. Точки расширения в классе Code Generated (LINQ to SQL, EF)
  2. Не компилируется в dll, если он не реализован (проверьте это с помощью .NET Reflector)
24
ответ дан 4 revs 25 September 2017 в 20:53
поделиться

Свойство Environment.UserInteractive .

Свойство UserInteractive сообщает значение false для процесса Windows или службы, подобной IIS, которая работает без пользовательского интерфейса. Если это свойство имеет значение false, не отображать модальные диалоговые окна или окна сообщений, потому что нет графического интерфейса пользователя, с которым пользователь мог бы взаимодействовать.

26
ответ дан GvS 25 September 2017 в 20:53
поделиться

Я не нашел никого, кто бы использовал string.Join для объединения строк с использованием разделителя Каждый продолжает писать один и тот же уродливый цикл

var sb = new StringBuilder();
var count = list.Count();
for(int i = 0; i < count; i++)
{
  if (sb.Length > 0) sb.Append(seperator);
  sb.Append(list[i]);
}

return sb.ToString();

вместо

return string.Join(separator, list.ToArray());
25
ответ дан 2 revs 25 September 2017 в 20:53
поделиться

Мне нравится использовать символ @ для запросов SQL. Он сохраняет sql красивым и отформатированным и без необходимости заключать в каждую строку разделитель строк.

string sql = @"SELECT firstname, lastname, email
               FROM users
               WHERE username = @username AND password = @password";
17
ответ дан Nathan Lee 25 September 2017 в 20:53
поделиться

Около всех прохладных были упомянуты. Не уверенный, если это известное или не

инициализация конструктора свойства/поля C#:

var foo = new Rectangle() 
{ 
    Fill = new SolidColorBrush(c), 
    Width = 20, 
    Height = 20 
};

Это создает прямоугольник и устанавливает перечисленные свойства.

я заметил что-то забавное - у Вас может быть запятая в конце списка свойств без него являющийся синтаксической ошибкой. Таким образом, это также допустимо:

var foo = new Rectangle() 
{ 
    Fill = new SolidColorBrush(c), 
    Width = 20, 
    Height = 20,
};
22
ответ дан 3 revs, 3 users 51% 25 September 2017 в 20:53
поделиться
  1. Я пока не могу комментировать, но учтите, что по умолчанию Visual Studio 2008 автоматически переходит через свойства, поэтому в этом случае атрибут DebuggerStepThrough больше не нужен.

  2. Кроме того, я не заметил, чтобы кто-то показывал, как объявлять лямбда без параметров (полезно для реализации Action <>)

    () => DoSomething(x);

Вы также должны прочитать о замыканиях - я не достаточно умен, чтобы объяснить их правильно. Но в основном это означает, что компилятор делает умные вещи, так что x в этой строке кода все равно будет работать, даже если он выходит из области видимости после создания лямбды.

  1. Недавно я также обнаружил, что вы можете притворяться, что игнорируете лямбда-параметр:

    (e, _) => DoSomething(e)

Это не совсем игнорирование, просто _ является действительным идентификатором. Таким образом, вы не можете игнорировать оба параметра, как это, но я думаю, что это своего рода аккуратный способ показать, что мы не заботимся об этом параметре (обычно это EventArgs, который имеет значение .Empty).

11
ответ дан 4 revs, 3 users 69% 25 September 2017 в 20:53
поделиться

Я вижу, что многие люди повторяют функциональность Nullable<T>.GetValueOrDefault(T).

19
ответ дан 2 revs, 2 users 67% 25 September 2017 в 20:53
поделиться

В C # есть несколько действительно скрытых ключевых слов и функций, связанных с недокументированным классом TypedReference. Следующие ключевые слова не имеют документов:

  • __makeref
  • __reftype
  • __refvalue
  • __arglist

Примеры использования:

// Create a typed reference
int i = 1;
TypedReference tr1 = __makeref(i);
// Get the type of a typed reference
Type t = __reftype(tr1);
// Get the value of a typed referece
int j = __refvalue(tr1, int); 
// Create a method that accepts and arbitrary number of typed references
void SomeMethod(__arglist) { ...
// Call the method
int x = 1;
string y = "Foo";
Object o = new Object();
SomeMethod(__arglist(x,y,o));
// And finally iterate over method parameters
void SomeMethod(__arglist) {
    ArgIterator ai = new ArgIterator(__arglist);
while(ai.GetRemainingCount() >0)
{
      TypedReference tr = ai.GetNextArg();
      Console.WriteLine(TypedReference.ToObject(tr));
}}
24
ответ дан 4 revs, 3 users 83% 25 September 2017 в 20:53
поделиться

C#?? пустой оператор объединения -

Едва ли скрытый, но редко используемый. Вероятно, потому что много разработчиков выполняет милю, когда они видят условное выражение? оператор, таким образом, они работают два, когда они видят этого.Б/У:

string mystring = foo ?? "foo was null"

, а не

string mystring;
if (foo==null)
    mystring = "foo was null";
else
    mystring = foo;
25
ответ дан 2 revs, 2 users 97% 25 September 2017 в 20:53
поделиться

Несколько человек упомянули , используя блоки, но я думаю, что они гораздо полезнее, чем думали люди. Думайте о них как об инструменте АОП бедного человека. У меня есть множество простых объектов, которые фиксируют состояние в конструкторе, а затем восстанавливают его в методе Dispose () . Это позволяет мне обернуть часть функциональности в блок , используя блок , и быть уверенным, что состояние восстанавливается в конце. Например:

using(new CursorState(this, BusyCursor));
{
    // Do stuff
}

CursorState фиксирует текущий курсор, используемый формой, затем устанавливает форму для использования поставляемого курсора. В конце он восстанавливает исходный курсор. Я делаю множество таких вещей, как, например, захват выборок и текущей строки в сетке перед обновлением и т. Д.

21
ответ дан 2 revs, 2 users 88% 25 September 2017 в 20:53
поделиться

Я опоздал на эту вечеринку, поэтому мой первый выбор уже сделан. Но я еще не видел, чтобы кто-нибудь упоминал этот драгоценный камень:

Параллельные расширения .NET Framework

В нем есть такие вещи, как заменить на Parallel.For или foreach на Parallel .ForEach


Параллельный образец:
Как вы думаете, сколько объектов CLR можно создать за одну секунду? enter image description here
См. Следующий пример:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;

namespace ObjectInitSpeedTest
{
   class Program
   {
       //Note: don't forget to build it in Release mode.
       static void Main()
       {
           normalSpeedTest();           
           parallelSpeedTest();

           Console.ForegroundColor = ConsoleColor.White;
           Console.WriteLine("Press a key ...");
           Console.ReadKey();
       }

       private static void parallelSpeedTest()
       {
           Console.ForegroundColor = ConsoleColor.Yellow;
           Console.WriteLine("parallelSpeedTest");

           long totalObjectsCreated = 0;
           long totalElapsedTime = 0;

           var tasks = new List<Task>();
           var processorCount = Environment.ProcessorCount;

           Console.WriteLine("Running on {0} cores", processorCount);

           for (var t = 0; t < processorCount; t++)
           {
               tasks.Add(Task.Factory.StartNew(
               () =>
               {
                   const int reps = 1000000000;
                   var sp = Stopwatch.StartNew();
                   for (var j = 0; j < reps; ++j)
                   {
                       new object();
                   }
                   sp.Stop();

                   Interlocked.Add(ref totalObjectsCreated, reps);
                   Interlocked.Add(ref totalElapsedTime, sp.ElapsedMilliseconds);
               }
               ));
           }

           // let's complete all the tasks
           Task.WaitAll(tasks.ToArray());

           Console.WriteLine("Created {0:N} objects in 1 sec\n", (totalObjectsCreated / (totalElapsedTime / processorCount)) * 1000);
       }

       private static void normalSpeedTest()
       {
           Console.ForegroundColor = ConsoleColor.Green;
           Console.WriteLine("normalSpeedTest");

           const int reps = 1000000000;
           var sp = Stopwatch.StartNew();
           sp.Start();
           for (var j = 0; j < reps; ++j)
           {
               new object();
           }
           sp.Stop();

           Console.WriteLine("Created {0:N} objects in 1 sec\n", (reps / sp.ElapsedMilliseconds) * 1000);
       }
   }
}
20
ответ дан 3 revs, 3 users 84% 25 September 2017 в 20:53
поделиться

Вы можете хранить цвета в Enum.

public enum MyEnumColors : uint
{
    Normal          = 0xFF9F9F9F,
    Active          = 0xFF8EA98A,
    Error           = 0xFFFF0000
}
16
ответ дан FFire 25 September 2017 в 20:53
поделиться

Один замечательный класс, который мне нравится, это System.Xml.XmlConvert, который можно использовать для чтения значений из тега xml. Особенно, если я читаю логическое значение из атрибута или элемента xml, я использую

bool myFlag  = System.Xml.XmlConvert.ToBoolean(myAttribute.Value);

Примечание: поскольку логический тип в xml принимает 1 и 0 в дополнение к «true» и «false» в качестве допустимых значений использование сравнения строк в этом случае подвержено ошибкам.

20
ответ дан 2 revs, 2 users 80%anon 25 September 2017 в 20:53
поделиться

псевдоним экстерна ключевое слово для ссылки на две версии блоков, которые имеют те же полностью определенные имена типов.

17
ответ дан 2 revs, 2 users 75% 25 September 2017 в 20:53
поделиться

От CLR через C#:

При нормализации строк, это настоятельно рекомендовано это, Вы используете ToUpperInvariant вместо ToLowerInvariant, потому что Microsoft оптимизировала код для выполнения прописных сравнений .

я помню одно время, мой коллега всегда менял струны к верхнему регистру перед сравнением. Я всегда задавался вопросом, почему он делает это, потому что я чувствую, что более "естественно" преобразовать в нижний регистр сначала. После чтения книги теперь я знаю почему.

438
ответ дан jfs 25 September 2017 в 20:53
поделиться
string.Empty

Я знаю, что это не фантастично (смешно странно), но я использую его все время вместо "".

И это довольно хорошо спрятано, пока кто-то не скажет вам, что он там.

20
ответ дан 4 revs, 2 users 75% 25 September 2017 в 20:53
поделиться

Когда класс реализует INotifyPropertyChanged и вы хотите сообщить системе привязки (WPF, Silverlight и т. Д.), Что несколько связанных свойств объекта (ViewModel) изменились, вы можете вызвать PropertyChanged-Event с помощью null или String.Empty .

Это задокументировано в MSDN, но примеры кода и статьи часто не объясняют эту возможность. Я нашел это очень полезным.

public class BoundObject : INotifyPropertyChanged {

    private int _value;
    private string _text;

    public event PropertyChangedEventHandler PropertyChanged;

    public int Value {
        get {
            return _value;
        }
        set {
            if (_value != value) {
                _value = value;
                OnPropertyChanged("Value");
            }
        }
    }

    public string Text {
        get {
            return _text;
        }
        set {
            if (_text != value) {
                _text = value;
                OnPropertyChanged("Text");
            }
        }
    }

    public void Init(){
        _text = "InitialValue";
        _value = 1;
        OnPropertyChanged(string.Empty);
    }

    public void Reset() {
        _text = "DefaultValue";
        _value = 0;
        OnPropertyChanged(string.Empty);
    }

    private void OnPropertyChanged(string propertyName) {
        PropertyChangedEventArgs e = new PropertyChangedEventArgs(propertyName);

        if (PropertyChanged != null) {
            PropertyChanged(this, e);
        }
    }
}
14
ответ дан Jehof 25 September 2017 в 20:53
поделиться

Извиняюсь за столь позднюю публикацию, я новичок в Stack Overflow, поэтому упустил ранее предоставленную возможность.

Я считаю, что EventHandler<T> является отличной чертой структуры, которая используется недостаточно.

Большинство разработчиков C #, с которыми я сталкиваюсь, все еще определяют собственный делегат обработчика событий, когда они определяют пользовательские события, которые просто больше не нужны.

Вместо:

public delegate void MyCustomEventHandler(object sender, MyCustomEventArgs e);

public class MyCustomEventClass 
{
    public event MyCustomEventHandler MyCustomEvent;
}

вы можете пойти:

public class MyCustomEventClass 
{
    public event EventHandler<MyCustomEventArgs> MyCustomEvent;
}

, что намного более кратко, плюс вы не попадаете в дилемму, ставить ли делегата в файле .cs для класса, который содержит событие, или производный класс EventArgs.

20
ответ дан 2 revs, 2 users 96% 25 September 2017 в 20:53
поделиться

Атрибуты Цели

Каждый видел один. В основном, когда вы видите это:

[assembly: ComVisible(false)]

Часть "assembly:" этого атрибута является целью. В этом случае атрибут применяется к сборке, но есть и другие:

[return: SomeAttr]
int Method3() { return 0; } 

В этом примере атрибут применяется к возвращаемому значению.

20
ответ дан Dave Van den Eynde 25 September 2017 в 20:53
поделиться

Директивы препроцессора могут быть изящными, если вы хотите различного поведения между режимами отладки и выпуска.

http://msdn.microsoft.com/en-us/library/ed8yd1ha.aspx

9
ответ дан John Asbeck 25 September 2017 в 20:53
поделиться

Также полезно, но обычно не используется: Области ограниченного исполнения .

Цитата из блога BCL Team:

Области ограниченного выполнения (CER) существуют, чтобы помочь разработчику написать свой код для обеспечения согласованности. CLR не гарантирует правильность кода разработчика, но CLR поднимает все точки сбоя, вызванные временем выполнения (т. Е. Асинхронные исключения), либо до выполнения кода, либо после его завершения. В сочетании с ограничениями на то, что разработчик может поместить в CER, это полезный способ создания надежных гарантий того, будет ли выполняться ваш код. CER с готовностью готовят, что означает, что когда мы их увидим, мы с нетерпением будем JIT любого кода, найденного в его статически обнаруживаемом графе вызовов. Если хост CLR заботится о переполнении стека, мы также проверим наличие некоторого количества стека (хотя, возможно, недостаточно стека для любого произвольного метода *). Мы также откладываем прерывание потока до завершения работы CER.

Это может быть полезно при внесении изменений в более чем одно поле структуры данных атомарным способом. Так что это помогает иметь транзакции на объектах.

Также CriticalFinalizerObject кажется скрытым (по крайней мере, те, кто не пишет небезопасный код). CriticalFinalizerObject гарантирует, что сборщик мусора выполнит финализатор. После распределения финализатор и его граф вызовов готовятся заранее.

15
ответ дан Incognito 25 September 2017 в 20:53
поделиться

Псевдонимы:

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

Позволяет использовать ASimpleName вместо Dictionary<string, Dictionary<string, List<string>>>.

Используйте его, когда вы будете использовать одну и ту же общую большую длинную сложную вещь во многих местах.

455
ответ дан 2 revs, 2 users 75% 25 September 2017 в 20:53
поделиться

лямбда-выражения и тип вывод недооценены. У лямбд может быть несколько операторов , и они автоматически дублируются как совместимый объект делегата (просто убедитесь, что подпись совпадает), как в:

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

Обратите внимание, что я надеваю У меня нет new CancellationEventHandler и мне не нужно указывать типы sender и e, они выводятся из события. Вот почему это менее обременительно при написании целого delegate (blah blah), которое также требует от вас указания типов параметров.

Лямбдам не нужно ничего возвращать , и вывод типа чрезвычайно мощен в таком контексте.

И кстати, вы всегда можете вернуть лямбды, которые делают лямбды в смысле функционального программирования. Например, вот лямбда, которая делает лямбду, которая обрабатывает событие Button.Click:

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

Обратите внимание на цепочку: (dx, dy) => (sender, e) =>

Вот почему я счастлив, что принял класс функционального программирования: -)

Кроме указателей в C, я думаю, что это еще одна фундаментальная вещь, которую вы должны изучить: -)

585
ответ дан 12 revs, 7 users 80% 25 September 2017 в 20:53
поделиться

Я становлюсь большим поклонником методов расширения, так как они могут добавить желаемую функциональность к существующему коду или коду, который вы не можете редактировать. Один из моих фаворитов, который я добавляю ко всему, что я сейчас делаю, - это string.IsNullOrEmpty ()

public static class Strings
{
    public static bool IsNullOrEmpty(this string value)
    {
        return string.IsNullOrEmpty(value);
    }
}

Это позволяет немного сократить код, подобный этому

var input = Console.ReadLine();
if (input.IsNullOrEmpty())
{
    Console.WriteLine("try again");
}
13
ответ дан 2 revs 25 September 2017 в 20:53
поделиться