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

Это пришло мне в голову после того, как я узнал следующее из этого вопроса :

where T : struct

Мы, разработчики C #, все знаем основы C #. Я имею в виду объявления, условия, циклы, операторы и т. Д.

Некоторые из нас даже освоили такие вещи, как Generics , анонимные типы , лямбда-выражения , LINQ , ...

Но каковы наиболее скрытые функции или уловки C #, о которых даже фанаты, наркоманы и эксперты C # едва знают?

Вот некоторые обнаруженные особенности:


Ключевые слова

Атрибуты

Синтаксис

Особенности языка

Возможности Visual Studio

Framework

Методы и свойства

  • String.IsNullOrEmpty() методом KiwiBastard
  • List.ForEach() методом KiwiBastard
  • BeginInvoke(), EndInvoke() методы по Уилл Дин
  • Nullable.HasValue и Nullable.Value свойства по Rismo
  • GetValueOrDefault метод Джона Шихана

Советы и рекомендации; Трюки

  • Хороший метод для обработчиков событий от Андреас Х.Р. Нильссон
  • Сравнение в верхнем регистре от Джон
  • Доступ к анонимным типам без отражения от dp
  • Быстрый способ ленивой реализации свойств коллекции с помощью Будет
  • JavaScript-подобных анонимных встроенных функций с помощью roosteronacid

Другие

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

256 ответов

Это не C# по сути, но я не видел никого, кто действительно использует System.IO.Path.Combine() до такой степени, что они должны. На самом деле целый класс Пути действительно полезен, но никто не использует его!

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

string path = dir + "\\" + fileName;
752
ответ дан ageektrapped 25 September 2017 в 20:53
поделиться

Мысль [приблизительно 114] @dp AnonCast и решенный для испытания его немного. Вот то, что я придумываю, который мог бы быть полезен для некоторых:

// using the concepts of dp's AnonCast
static Func<T> TypeCurry<T>(Func<object> f, T type)
{
    return () => (T)f();
}

И вот то, как это могло бы использоваться:

static void Main(string[] args)
{

    var getRandomObjectX = TypeCurry(GetRandomObject,
        new { Name = default(string), Badges = default(int) });

    do {

        var obj = getRandomObjectX();

        Console.WriteLine("Name : {0} Badges : {1}",
            obj.Name,
            obj.Badges);

    } while (Console.ReadKey().Key != ConsoleKey.Escape);

}

static Random r = new Random();
static object GetRandomObject()
{
    return new {
        Name = Guid.NewGuid().ToString().Substring(0, 4),
        Badges = r.Next(0, 100)
    };
}
6
ответ дан 3 revs, 2 users 97% 25 September 2017 в 20:53
поделиться

Математика. Max и Min для проверки границ: Я 've замеченный это в большом количестве кода:

if (x < lowerBoundary) 
{
   x = lowerBoundary;
}

я нахожу это меньшим, более чистым и более читаемым:

x = Math.Max(x, lowerBoundary);

Или можно также использовать тернарный оператор:

x = ( x < lowerBoundary) ? lowerBoundary : x;
6
ответ дан 2 revs 25 September 2017 в 20:53
поделиться

Это не определенная функция C#, но это - дополнение, которое я нахожу очень полезными. Это называют Инструментом Рефакторинга Ресурса. Это позволяет Вам щелкать правой кнопкой по литеральной строке и извлекать его в файл ресурсов. Это будет искать код и находить любые другие литеральные строки, которые соответствуют и заменяют его тем же ресурсом из файла Resx.

http://www.codeplex.com/ResourceRefactoring

6
ответ дан Steven Behnke 25 September 2017 в 20:53
поделиться

(Я просто использовал этого), Набор полевой пустой указатель, и возвратите его без промежуточной переменной:

try
{
    return _field;
}
finally
{
    _field = null;
}
6
ответ дан Bryan Watts 25 September 2017 в 20:53
поделиться

@lainMH,

булевские переменные Nullable полезны при получении значений от базы данных, которые nullable и при откладывании значений в. Иногда Вы хотите знать, что поле не было установлено.

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

Без определенного порядка:

Lists<>
Mutex

новый ярлык определений свойства в Платформе 3.5.

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

Я не обнаружил - в течение почти года - что DataRows Со строгим контролем типов содержат [ColumnName] Пустой указатель () метод.

, Например:

Units.UnitsDataTable dataTable = new Units.UnitsDataTable();

foreach (Units.UnitsRow row in dataTable.Rows)
{
    if (row.IsPrimaryKeyNull())
        //....

    if (row.IsForeignKeyNull())
        //....
}
5
ответ дан Gavin Miller 25 September 2017 в 20:53
поделиться

Универсальный обработчик событий:

public event EventHandler<MyEventArgs> MyEvent;

Этот путь Вы не должны объявлять своих собственных делегатов все время,

5
ответ дан Johan S 25 September 2017 в 20:53
поделиться

Отражение Испускает, и Деревья выражений приходят на ум...

не пропускают CLR Jeffrey Richter через C#, и Jon Skeet alt text

Посмотрите здесь для некоторых ресурсов:

http://www.codeproject.com/KB/trace/releasemodebreakpoint.aspx

http://www.codeproject.com/KB/dotnet/Creating_Dynamic_Types.aspx

http://www.codeproject.com/KB/cs/lambdaexpressions.aspx

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

В чтении книги по разработке платформы.NET. Хороший совет не должен использовать bool, чтобы включить или выключить материал, а скорее использовать Перечисления.

С Перечислениями Вы даете себе некоторую расширяемость, не имея необходимость переписывать любой код для добавления новой опции к функции.

6
ответ дан David Basarab 25 September 2017 в 20:53
поделиться

динамическое ключевое слово в C# 4.0

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

dynamic invoker=new DynamicInvoker();
dynamic result1=invoker.MyMethod1();
dynamic result2=invoker.MyMethod2();

Здесь я реализую динамический invoker.

public class DynamicInvoker : IDynamicObject
    {
        public MetaObject GetMetaObject
              (System.Linq.Expressions.Expression parameter)
        {
            return new DynamicReaderDispatch (parameter);
        }
    }

    public class DynamicDispatcher : MetaObject
    {
        public DynamicDispatcher (Expression parameter) 
                   : base(parameter, Restrictions.Empty){ }

        public override MetaObject Call(CallAction action, MetaObject[] args)
        {
            //You'll get MyMethod1 and MyMethod2 here (and what ever you call)
            Console.WriteLine("Logic to invoke Method '{0}'", action.Name);
            return this; //Return a meta object
        }
    }
7
ответ дан amazedsaint 25 September 2017 в 20:53
поделиться

членская реализация интерфейса Explicit , где интерфейсный участник реализован, но скрыт, если экземпляр не брошен к интерфейсному типу.

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

Не определенная вещь C#, но я - троичный операционный наркоман.

Вместо

if (boolean Condition)
{
    //Do Function
}
else
{
    //Do something else
}

можно использовать сжатое

booleanCondtion ? true operation : false operation;

, например,

Вместо

int value = param;
if (doubleValue)
{
    value *= 2;
}
else
{
    value *= 3;
}

можно ввести

int value = param * (tripleValue ? 3 : 2);

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

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

Я вполне уверен, все знакомы с перегрузкой оператора, но возможно некоторые не.

class myClass
{
    private string myClassValue = "";

    public myClass(string myString)
    {
        myClassValue = myString;
    }

    public override string ToString()
    {
        return myClassValue;
    }

    public static myClass operator <<(myClass mc, int shiftLen)
    {
        string newString = "";
        for (int i = shiftLen; i < mc.myClassValue.Length; i++)
            newString += mc.myClassValue[i].ToString();
        mc.myClassValue = newString.ToString();
        return mc;
    }

    public static myClass operator >>(myClass mc, int shiftLen)
    {
        char[] newString = new char[shiftLen + mc.myClassValue.Length];

        for (int i = shiftLen; i < mc.myClassValue.Length; i++)
            newString[i] += mc.myClassValue[i - shiftLen];

        mc.myClassValue = new string(newString);
        return mc;
    }

    public static myClass operator +(myClass mc, string args)
    {
        if (args.Trim().Length > 1)
            mc.myClassValue += args;
        return mc;
    }

    public static myClass operator -(myClass mc, string args)
    {
        if (args.Trim().Length > 1)
        {
            Regex rgx = new Regex(args);
            mc.myClassValue = rgx.Replace(mc.myClassValue, "");
        }
        return mc;
    }
}

я думаю, что довольно здорово быть в состоянии сместить строку левое и правое использование < < и>> или удалить ряд строк, которые следуют за использованием образца регулярного выражения - =

myClass tmpClass = new myClass("  HelloWorld123");
tmpClass -= @"World";
tmpClass <<= 2;
Console.WriteLine(tmpClass);
8
ответ дан SemiColon 25 September 2017 в 20:53
поделиться

Mixins являются хорошей функцией. В основном mixins позволяют Вам иметь конкретный код для интерфейса вместо класса. Затем просто реализуйте интерфейс в наборе классов, и Вы автоматически получаете смешивание функциональности. Например, для смешивания в глубоком копировании в несколько классов определите интерфейс

internal interface IPrototype<T> { }

, Добавляет функциональность для этого интерфейса

internal static class Prototype
{
  public static T DeepCopy<T>(this IPrototype<T> target)
  {
    T copy;
    using (var stream = new MemoryStream())
    {
      var formatter = new BinaryFormatter();
      formatter.Serialize(stream, (T)target);
      stream.Seek(0, SeekOrigin.Begin);
      copy = (T) formatter.Deserialize(stream);
      stream.Close();
    }
    return copy;
  }
}

Тогда интерфейс реализации в любом типе для получения смешивания.

6
ответ дан Dmitri Nesteruk 25 September 2017 в 20:53
поделиться

Можно включить строку!

switch(name)
{
  case "Dave":
    return true;
  case "Bob":
    return false;
  default:
    throw new ApplicationException();
}

Очень удобный! и намного более чистый, чем набор если еще операторы

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

В дополнение к ответу duncansmart также дополнительные методы могут использоваться на Платформе 2.0. Просто добавьте ExtensionAttribute класс под Системой. Время выполнения. Пространство имен CompilerServices и Вы можете использовать дополнительные методы (только с C# 3.0, конечно).

namespace System.Runtime.CompilerServices
{
    public class ExtensionAttribute : Attribute
    { 
    }
}
7
ответ дан 2 revs, 2 users 88% 25 September 2017 в 20:53
поделиться

Объект. Метод ReferenceEquals

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

Параметры:

  • objA: Система. Объект - первый Объект выдержать сравнение.
  • objB: Система. Объект - второй Объект выдержать сравнение.

Пример:

 object o = null;
 object p = null;
 object q = new Object();

 Console.WriteLine(Object.ReferenceEquals(o, p));
 p = q;
 Console.WriteLine(Object.ReferenceEquals(p, q));
 Console.WriteLine(Object.ReferenceEquals(o, p));

Различие к "==" и ".Equals":

В основном, Равняется (), тесты объекта A имеют то же содержание как объект B.

Система метода. Объект. ReferenceEquals () всегда сравнивает ссылки. Хотя класс может обеспечить свое собственное поведение для оператора равенства (ниже), что переопределенный оператор не вызывается, если оператор называют через ссылку на Систему. Объект.

Для строк нет действительно различия, потому что и == и Равняется, были переопределены для сравнения содержания строки.

Видят также этот ответ к другому вопросу ("Как я проверяю на пустые указатели в †˜ == перегрузка оператора ’ без бесконечной рекурсии?").

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

@Brad Barker

я думаю, необходимо ли использовать nullable типы, лучше использовать Nullable<.T>, а не нотация вопросительного знака. Это делает его глазом ноюще очевидный, что волшебство происходит. Не уверенный, почему любой когда-либо хотел бы использовать Nullable< .bool> все же.:-)

у Krzysztof Cwalina (один из авторов Инструкций по Дизайну Framwork) есть хорошее сообщение здесь: http://blogs.msdn.com/kcwalina/archive/2008/07/16/Nullable.aspx

И Mike Hadlow имеет хорошее сообщение на Nullability Voodoo

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

новый модификатор

Использование "нового" модификатора в C# не точно скрыто, но это не часто замечается. Новый модификатор пригождается, когда необходимо "скрыть" участников базового класса и не всегда переопределять их. Это означает, когда Вы снимаете производный класс в качестве базового класса тогда, "скрытый" метод становится видимым и назван вместо того же метода в производном классе.

легче видеть в коде:

public class BaseFoo
{
    virtual public void DoSomething()
    {
        Console.WriteLine("Foo");
    }
}

public class DerivedFoo : BaseFoo
{
    public new void DoSomething()
    {
        Console.WriteLine("Bar");
    }
}

public class DerivedBar : BaseFoo
{
    public override void DoSomething()
    {
        Console.WriteLine("FooBar");
    }
}

class Program
{
    static void Main(string[] args)
    {
        BaseFoo derivedBarAsBaseFoo = new DerivedBar();
        BaseFoo derivedFooAsBaseFoo = new DerivedFoo();

        DerivedFoo derivedFoo = new DerivedFoo();

        derivedFooAsBaseFoo.DoSomething(); //Prints "Foo" when you might expect "Bar"
        derivedBarAsBaseFoo.DoSomething(); //Prints "FooBar"

        derivedFoo.DoSomething(); //Prints "Bar"
    }
}

[Ed: я понимаю дополнительные мысли для игры слов? Извините, не мог помочься.]

6
ответ дан Sixto Saez 25 September 2017 в 20:53
поделиться

Я нахожу эту технику интересной при работе с linqxml:

public bool GetFooSetting(XElement ndef){
   return (bool?)ndef.Element("MyBoolSettingValue") ?? true;
}

в противоположность:

public bool GetFooSetting(XElement ndef){
   return ndef.Element("MyBoolSettingValue") != null ? bool.Parse(ndef.Element("MyBoolSettingValue") ) : true;
}
5
ответ дан 2 revs, 2 users 92% 25 September 2017 в 20:53
поделиться

Литералы могут использоваться в качестве переменных того типа. например,

Console.WriteLine(5.ToString());
Console.WriteLine(5M.GetType());   // Returns "System.Decimal"
Console.WriteLine("This is a string!!!".Replace("!!", "!"));

Просто немного мелочи...

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

проверенные/непроверенные ключевые слова:

public static int UncheckedAddition(int a, int b)
{
    unchecked { return a + b; }
}

public static int CheckedAddition(int a, int b)
{
    checked { return a + b; } // or "return checked(a + b)";
}

public static void Main() 
{
    Console.WriteLine("Unchecked: " + UncheckedAddition(Int32.MaxValue, + 1));  // "Wraps around"
    Console.WriteLine("Checked: " + CheckedAddition(Int32.MaxValue, + 1));  // Throws an Overflow exception
    Console.ReadLine();
}
6
ответ дан 2 revs 25 September 2017 в 20:53
поделиться

Некоторые утилиты параллелизма в BCL могли бы квалифицировать как скрытые функции.

Вещи как Система. Поточная обработка. Монитор используется внутренне ключевым словом блокировки; ясно в C# ключевое слово блокировки предпочтительно, но иногда это платит, чтобы знать, как вещи сделаны на более низком уровне; я должен был привязать C++ / CLI, таким образом, я монтировал в корпус блок кода с вызовами для Контроля. Войдите () и Монитор. Выход ().

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

Относительно foreach: Это не использует 'утиный ввод', поскольку утка, вводящая IMO, обращается к проверке на этапе выполнения. Это использует структурный тип, проверяющий (в противоположность номиналу) во время компиляции для проверки на требуемый метод в типе.

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

Видел упоминание о Списке. ForEach выше; 2.0 представил собрание основанных на предикате операций набора - Находят, FindAll, Существует, и т.д. Вместе с анонимными делегатами, можно почти достигнуть простоты 3.5's лямбда-выражения.

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

Robbie Rocketpants

, "но мои инстинкты говорит мне, что это сократило бы максимум два, вводят, разрушает операции к максимуму одного".

, Если Вы делаете бросок, как Вы предполагали в примере 1 (использование является & как), это приводит к 2 вызовам к "," оператор. Поскольку то, когда Вы делаете "c = obj как MyClass", сначала он звонит "," негласно, тогда если он приводит это к сбою, он просто возвращает пустой указатель.

, Если Вы делаете бросок, как Вы предполагали в примере 2,

c = (MyClass)obj

Тогда, это на самом деле работает "," операция снова, тогда если это приводит ту проверку к сбою, это выдает исключение (InvalidCastException).

Так, если Вы хотели сделать легкий динамический бросок, лучше делать 3-й пример, который Вы обеспечили:

MyClass c;
if (obj is MyClass)
{
    c = obj as MyClass
}

if (c != null)
{
}

по сравнению с [1 113]

MyClass c = obj as MyClass;

if (c != null)
{
}

Вы видите, который более быстр, более краток и более ясен.

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

Вы вводите "опору" и затем нажимаете [TAB] дважды, это генерирует полезный код для Ваших свойств и может ускорить Ваш ввод.

я знаю, что это работает в VS 2005 (я использую его), но я donВґt знаю в предыдущих версиях.

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

Это не определенный тип C#, но я просто нашел интерфейсы ISurrogateSelector и ISerializationSurrogate -

http://msdn.microsoft.com/en-us/library/system.runtime.serialization.isurrogateselector.aspx

, http://msdn.microsoft.com/en-us/library/system.runtime.serialization.isurrogateselector.aspx

Используя их в сочетании с BinaryFormatter позволяет, чтобы несериализуемые объекты были сериализированы через реализацию суррогатного класса. Суррогатный шаблон хорошо понят в информатике, особенно при контакте с проблемой сериализации. Я думаю, что эта реализация просто убрана как параметр конструктора к BinaryFormatter, и очень жаль.

Все еще - ОЧЕНЬ скрытый.:)

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

Вместо того, чтобы использовать интервал. TryParse () или Преобразовывают. ToInt32 (), мне нравится иметь статическую целочисленную функцию парсинга, которая возвращает пустой указатель, когда это не может проанализировать. Тогда я могу использовать?? и тернарный оператор вместе, чтобы более ясно гарантировать мое объявление и инициализацию все сделан на одной строке легким для понимания способом.

public static class Parser {
    public static int? ParseInt(string s) {
        int result;
        bool parsed = int.TryParse(s, out result);
        if (parsed) return result;
        else return null;
    }
    // ...
}

Этого также хорошо постараться не копировать левую сторону присвоения, но еще лучше стараться не копировать долгие запросы к правой стороне присвоения, такие как база данных звонит в следующий пример. Вместо ужасного, если тогда деревья (с которым я часто сталкиваюсь):

int x = 0;
YourDatabaseResultSet data = new YourDatabaseResultSet();
if (cond1)
    if (int.TryParse(x_input, x)){
        data = YourDatabaseAccessMethod("my_proc_name", 2, x);
    }
    else{
        x = -1;
        // do something to report "Can't Parse"    
    }
}
else {
    x = y;
    data = YourDatabaseAccessMethod("my_proc_name", 
       new SqlParameter("@param1", 2),
       new SqlParameter("@param2", x));
}

можно сделать:

int x = cond1 ? (Parser.ParseInt(x_input) ?? -1) : y;
if (x >= 0)  data = YourDatabaseAccessMethod("my_proc_name", 
    new SqlParameter("@param1", 2),
    new SqlParameter("@param2", x));

Намного более чистый и легче понять

6
ответ дан Patrick Szalapski 25 September 2017 в 20:53
поделиться