Скрытые возможности 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 ответов

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

protected void GridView1_RowCommand(object sender, GridViewCommandEventArgs e)
    {
        //if (e.CommandName == "sel")
        //{
        //    lblCat.Text = e.CommandArgument.ToString();
        //}
    }

В приведенном выше коде, если я хочу выбрать:

e.CommandName == "sel"

lblCat.Text = e.Comman

Затем я нажимаю клавишу ALt и выбираю прямоугольник и не нужно раскомментировать строки.

Проверьте это.

48
ответ дан 22 November 2019 в 20:19
поделиться

C # + CLR:

  1. Thread.MemoryBarrier : Большинство людей не использовали бы его, и в MSDN есть некоторая неточная информация. Но если вы знакомы с тонкостями , тогда вы можете выполнять изящную синхронизацию без блокировок.

  2. volatile, Thread.VolatileRead, Thread.VolatileWrite : очень мало людей используют их и еще меньше тех, кто понимает все риски, которых они избегают и создают :)

  3. Переменные ThreadStatic : За последние несколько лет была только одна ситуация, я обнаружил, что переменные ThreadStatic были абсолютно незаменимыми. Например, если вы хотите что-то сделать для всей цепочки вызовов, они очень полезны.

  4. fixed keyword: It ' скрытое оружие, когда вы хотите сделать доступ к элементам большого массива почти так же быстро, как C ++ (по умолчанию C # применяет связанные проверки, что замедляет работу).

  5. ключевое слово default (typeName) может использоваться вне общего класса также. Полезно создать пустую копию структуры.

  6. Одной из удобных функций, которые я использую, является DataRow [columnName] .ToString () всегда возвращает ненулевое значение. Если значение в базе данных было ПУСТО (NULL), вы получите пустую строку.

  7. Используйте объект Debugger для автоматического прерывания, если вы хотите привлечь внимание разработчика, даже если он / она не включил автоматический прерывание при исключении:


#if DEBUG  
    if (Debugger.IsAttached)  
        Debugger.Break();  
#endif
  1. Вы можете использовать псевдоним сложного уродливого общего типы, поэтому вам не нужно копировать и вставлять их снова и снова. Также вы можете вносить изменения в этот тип в одном месте. Например,

    using ComplicatedDictionary = Dictionary<int, Dictionary<string, object>>;
    ComplicatedDictionary myDictionary = new ComplicatedDictionary();
39
ответ дан 22 November 2019 в 20:19
поделиться

При отладке вы можете ввести $exception в окне Watch\QuickWatch\Immediate и получить всю информацию об исключении текущего кадра. Это очень полезно, если у вас включены исключения первого шанса!

69
ответ дан 22 November 2019 в 20:19
поделиться

Вот новый метод строкового класса в C # 4.0:

String.IsNullOrWhiteSpace(String value)

Пора.

72
ответ дан 22 November 2019 в 20:19
поделиться

Я прочитал все семь страниц, и мне не хватает этих:

String.Join

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

String.Join(",", new String[] { "a", "b", "c"});

TODO in comment

Не совсем функция C #, скорее функция Visual Studio. Когда вы начинаете свой комментарий с TODO, он добавляется в ваш список задач Visual Studio (Вид -> Список задач. Комментарии)

// TODO: Implement this!
throw new NotImplementedException();

Методы расширения соответствуют универсальным

Вы можете комбинировать методы расширения с универсальными шаблонами, если вспомните совет ранее в этой теме вы можете добавить расширения к определенным интерфейсам

public static void Process<T>(this T item) where T:ITest,ITest2 {}

Enumerable.Range

Хотите список целых чисел?

Enumerable.Range(0, 15)

Я попробую придумать еще кое-что ...

32
ответ дан 22 November 2019 в 20:19
поделиться

Произвольные вложенные области видимости {}


1. Для более точного определения области действия

{ в любом месте внутри элементов } , { с использованием только фигурных скобок } , { без контроля заявление } .

void MyWritingMethod() {

    int sameAge = 35;


    { // scope some work
        string name = "Joe";
        Log.Write(name + sameAge.ToString());
    }


    { // scope some other work
        string name = "Susan";
        Log.Write(name + sameAge.ToString());
    }

    // I'll never mix up Joe and Susan again
}

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

2. Для украшения кода или визуальной семантики

. Например, этот код записи XML следует уровню отступа фактически сгенерированного XML (т.е. Visual Studio будет соответственно отступать скобками области видимости)

XmlWriter xw = new XmlWriter(..);

//<root>
xw.WriteStartElement("root");
{
    //<game>
    xw.WriteStartElement("game");
    {
        //<score>#</score>
        for (int i = 0; i < scores.Length; ++i) // multiple scores
            xw.WriteElementString("score", scores[i].ToString());

    }
    //</game>
    xw.WriteEndElement();
}
//</root>
xw.WriteEndElement();

3. Имитация оператора «with»

(Также еще одно применение, чтобы держать временную работу вне основной области действия)
Предоставлено Patrik : иногда используется для имитации VB «with- оператор "в C #.

var somePerson = this.GetPerson();  // whatever 
{ 
    var p = somePerson; 
    p.FirstName = "John"; 
    p.LastName = "Doe"; 
    //... 
    p.City = "Gotham"; 
} 

Для взыскательного программиста.

35
ответ дан 22 November 2019 в 20:19
поделиться

RealProxy позволяет создавать собственные прокси для существующих типов.

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

По сути, класс .NET RealProxy позволяет создавать так называемые прозрачные прокси для другого типа. Прозрачность в этом случае означает, что он полностью похож на проксируемый целевой объект для своего клиента, но на самом деле это не так: это экземпляр вашего класса, производный от RealProxy.

Это позволяет вам применять мощные и всесторонние сервисы перехвата и «посредничества» между клиентом и любыми методами или свойствами, вызванными на реальном целевом объекте. Соедините эту мощь с фабричным шаблоном (IoC и т. Д.), И вы сможете вернуть прозрачные прокси вместо реальных объектов, что позволит вам перехватывать все вызовы реальных объектов и выполнять действия до и после каждого вызова метода. Фактически, я считаю, что это та самая функциональность, которую .NET использует для удаленного взаимодействия между доменами приложения, процессами и границами компьютеров: .NET перехватывает весь доступ, отправляет сериализованную информацию удаленному объекту, получает ответ и возвращает его вашему коду.

Может быть, пример прояснит, как это может быть полезно: я создал стек справочных служб для моей последней работы в качестве архитектора предприятия, который определил стандартный внутренний состав («стек») любых новых служб WCF в подразделении. Модель требовала, чтобы уровень доступа к данным (скажем) для службы Foo реализовал IDAL : создавал Foo, читал Foo, обновлял Foo, удалял Foo. Разработчики сервисов использовали предоставленный общий код (от меня), который находил и загружал требуемый DAL для сервиса:

IDAL<T> GetDAL<T>(); // retrieve data access layer for entity T

Стратегии доступа к данным в этой компании часто были, ну, в общем, проблемы с производительностью. Как архитектор, я не мог следить за каждым разработчиком сервисов, чтобы убедиться, что он / она написал эффективный уровень доступа к данным. Но то, что я мог сделать в рамках фабричного шаблона GetDAL , - это создать прозрачный прокси для запрошенного DAL (как только код модели общего обслуживания обнаружил DLL и загрузил ее) и использовать высокий уровень API синхронизации производительности для профилирования всех вызовов любого метода DAL. Таким образом, ранжирование отстающих - это просто сортировка таймингов вызовов DAL по убыванию общего времени. Преимущество этого по сравнению с профилированием разработки (например, в среде IDE) состоит в том, что его можно выполнять и в производственной среде, чтобы гарантировать SLA.

Вот пример тестового кода, который я написал для «профилировщика объектов», который представлял собой общий код для создания прокси-сервера профилирования для любого типа с помощью одной строки:

[Test, Category("ProfileEntity")]
public void MyTest()
{
    // this is the object that we want profiled.
    // we would normally pass this around and call
    // methods on this instance.
    DALToBeProfiled dal = new DALToBeProfiled();

    // To profile, instead we obtain our proxy
    // and pass it around instead.
    DALToBeProfiled dalProxy = (DALToBeProfiled)EntityProfiler.Instance(dal);

    // or...
    DALToBeProfiled dalProxy2 = EntityProfiler<DALToBeProfiled>.Instance(dal);

    // Now use proxy wherever we would have used the original...
    // All methods' timings are automatically recorded
    // with a high-resolution timer
    DoStuffToThisObject(dalProxy);

    // Output profiling results
    ProfileManager.Instance.ToConsole();
}

Опять же, это позволяет вам перехватывать все вызываемые методы и свойства клиентом на целевом объекте! В вашем классе , производном от RealProxy, вы должны переопределить Invoke:

[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
[SecurityPermission(SecurityAction.LinkDemand, 
    Flags = SecurityPermissionFlag.Infrastructure)] // per FxCop
public override IMessage Invoke(IMessage msg)
{
    IMethodCallMessage msgMethodCall = msg as IMethodCallMessage;
    Debug.Assert(msgMethodCall != null); // should not be null - research Invoke if this trips. KWB 2009.05.28

    // The MethodCallMessageWrapper
    // provides read/write access to the method 
    // call arguments. 
    MethodCallMessageWrapper mc =
        new MethodCallMessageWrapper(msgMethodCall);

    // This is the reflected method base of the called method. 
    MethodInfo mi = (MethodInfo)mc.MethodBase;

    IMessage retval = null;

    // Pass the call to the method and get our return value
    string profileName = ProfileClassName + "." + mi.Name;

    using (ProfileManager.Start(profileName))
    {
        IMessage myReturnMessage =
           RemotingServices.ExecuteMessage(_target, msgMethodCall);

        retval = myReturnMessage;
    }

    return retval;
}

Разве не интересно, что умеет .NET? Единственное ограничение состоит в том, что целевой тип должен быть производным от MarshalByRefObject . Надеюсь, это кому-то поможет.

36
ответ дан 22 November 2019 в 20:19
поделиться

Программисты, переходящие с C / C ++, могут пропустить это:

В C #% (оператор модуля) работает с числами с плавающей запятой!

26
ответ дан 22 November 2019 в 20:19
поделиться

Анонимные встроенные функции, подобные JavaScript

Возвращают строку:

var s = new Func<String>(() =>
{
    return "Hello World!";
})();

Возвращают более сложный объект:

var d = new Func<Dictionary<Int32, String>>(() =>
{
    return new Dictionary<Int32, String>
    {
        { 0, "Foo" },
        { 1, "Bar" },
        { 2, "..." }
    };
})();

Реальный вариант использования:

var tr = new TableRow();

tr.Cells.AddRange
(
    new[]
    {
        new TableCell { Text = "" },
        new TableCell { Text = "" },
        new TableCell { Text = "" },

        new TableCell
        {
            Text = new Func<String>(() =>
            {
                return @"Result of a chunk of logic, without having to define
                         the logic outside of the TableCell constructor";
            })()
        },

        new TableCell { Text = "" },
        new TableCell { Text = "" }
    }
);

Примечание: вы не может повторно использовать имена переменных внутри области действия встроенной функции.


Альтернативный синтаксис

// The one-liner
Func<Int32, Int32, String> Add = (a, b) => Convert.ToString(a + b);

// Multiple lines
Func<Int32, Int32, String> Add = (a, b) =>
{
    var i = a + b;

    return i.ToString();
};

// Without parameters
Func<String> Foo = () => "";

// Without parameters, multiple lines
Func<String> Foo = () =>
{
    return "";
};

Сократите строку и добавьте горизонтальное многоточие ...

Func<String, String> Shorten = s => s.Length > 100 ? s.Substring(0, 100) + "&hellip;" : s;
28
ответ дан 22 November 2019 в 20:19
поделиться

Вы можете «использовать» несколько объектов в одном операторе using.

using (Font f1= new Font("Arial", 10.0f), f2 = new Font("Arial", 10.0f))
{
    // Use f1 and f2.
}

Обратите внимание, что там уже есть ответ о том, что вы можете это сделать:

using (Font f1= new Font("Arial", 10.0f))
using (Font f2 = new Font("Arial", 10.0f))
{    }

Это отличается от моего.

31
ответ дан 22 November 2019 в 20:19
поделиться

Легко определить тип, с которым переменная была объявлена ​​ (из мой ответ ):

using System;
using System.Collections.Generic;

static class Program
{
    public static Type GetDeclaredType<T>(T x)
    {
        return typeof(T);
    }

    // Demonstrate how GetDeclaredType works
    static void Main(string[] args)
    {
        IList<string> iList = new List<string>();
        List<string> list = null;

        Console.WriteLine(GetDeclaredType(iList).Name);
        Console.WriteLine(GetDeclaredType(list).Name);
    }
}

Результаты:

IList`1
List`1

И его имя (заимствовано из «Получить имя переменной» ):

static void Main(string[] args)
{
    Console.WriteLine("Name is '{0}'", GetName(new {args}));
    Console.ReadLine();
}

static string GetName<T>(T item) where T : class
{
    var properties = typeof(T).GetProperties();
    return properties[0].Name;
}

Результат: Имя - 'args'

27
ответ дан 22 November 2019 в 20:19
поделиться

Я обнаружил, что лишь немногие разработчики знают об этой функции.

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

Пример кода:

using System;
using System.Collections;

interface IFoo {
    void Foo();
}
struct MyStructure : IFoo {
    public void Foo() {
    }
}
public static class Program {
    static void MethodDoesNotBoxArguments<T>(T t) where T : IFoo {
        t.Foo();
    }
    static void Main(string[] args) {
        MyStructure s = new MyStructure();
        MethodThatDoesNotBoxArguments(s);
    }
}

Код IL не содержит любые инструкции в блоке:

.method private hidebysig static void  MethodDoesNotBoxArguments<(IFoo) T>(!!T t) cil managed
{
  // Code size       14 (0xe)
  .maxstack  8
  IL_0000:  ldarga.s   t
  IL_0002:  constrained. !!T
  IL_0008:  callvirt   instance void IFoo::Foo()
  IL_000d:  ret
} // end of method Program::MethodDoesNotBoxArguments

.method private hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint
  // Code size       15 (0xf)
  .maxstack  1
  .locals init ([0] valuetype MyStructure s)
  IL_0000:  ldloca.s   s
  IL_0002:  initobj    MyStructure
  IL_0008:  ldloc.0
  IL_0009:  call       void Program::MethodDoesNotBoxArguments<valuetype MyStructure>(!!0)
  IL_000e:  ret
} // end of method Program::Main

См. Рихтер, J. CLR через C # , 2-е издание, глава 14: Интерфейсы, раздел об универсальных шаблонах и интерфейсных ограничениях.

См. также мой ответ на другой вопрос.

23
ответ дан 22 November 2019 в 20:19
поделиться

ширина в string.Format()

Console.WriteLine("Product: {0,-7} Price: {1,5}", product1, price1);
Console.WriteLine("Product: {0,-7} Price: {1,5}", product2, price2);

производит

alt text

из Prabir's Blog | Скрытая возможность C#

31
ответ дан 22 November 2019 в 20:19
поделиться

typedefs

Кто-то написал, что они пропускают typedefs, но вы можете сделать это так

using ListOfDictionary = System.Collections.Generic.List<System.Collections.Generic.Dictionary<string, string>>;

и объявить это как

ListOfDictionary list = new ListOfDictionary();
31
ответ дан 22 November 2019 в 20:19
поделиться

Событие AppDomain.UnhandledException Event также является кандидатом на скрытие.

Это событие обеспечивает уведомление о неперехваченных исключениях. Оно позволяет приложению записать информацию об исключении до того, как системный обработчик по умолчанию сообщит об исключении пользователю и завершит работу приложения. Если имеется достаточно информации о состоянии приложения, могут быть предприняты другие действия - например, сохранение данных программы для последующего восстановления. Рекомендуется соблюдать осторожность, поскольку данные программы могут быть повреждены, если исключения не обрабатываются.

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

26
ответ дан 22 November 2019 в 20:19
поделиться

Мой любимый атрибут: InternalsVisibleTo

На уровне сборки вы можете объявить, что ваша сборка может видеть другая сборка. , Для целей тестирования это абсолютно замечательно.

Вставьте это в файл AssemblyInfo.cs или аналогичный, и ваша тестовая сборка получит полный доступ ко всем внутренним компонентам, требующим тестирования.

[assembly: InternalsVisibleTo("MyLibrary.Test, PublicKey=0024...5c042cb")]

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

Доступно в .Net Framework 2.0+, Compact Framework 2.0+ и XNA Framework 1.0+.

18
ответ дан 22 November 2019 в 20:19
поделиться

Вы можете добавлять и удалять делегатов с меньшим набором текста.

Обычный способ:

handler += new EventHandler(func);

Меньше набора текста:

handler += func;
15
ответ дан 22 November 2019 в 20:19
поделиться

При определении настраиваемых атрибутов вы можете использовать их с [MyAttAttribute] или с [MyAtt]. Когда классы существуют для обеих записей, возникает ошибка компиляции.

Для их различения можно использовать специальный символ @:

[AttributeUsage(AttributeTargets.All)]
public class X: Attribute
{}

[AttributeUsage(AttributeTargets.All)]
public class XAttribute: Attribute
{}

[X]      // Error: ambiguity
class Class1 {}

[XAttribute]   // Refers to XAttribute
class Class2 {}

[@X]      // Refers to X
class Class3 {}

[@XAttribute]   // Refers to XAttribute
class Class4 {}
14
ответ дан 22 November 2019 в 20:19
поделиться

Вы можете ограничить срок службы и, следовательно, объем переменных, используя квадратные скобки {} .

{
    string test2 = "3";
    Console.Write(test2);
}

Console.Write(test2); //compile error

test2 живет только в квадратных скобках.

17
ответ дан 22 November 2019 в 20:19
поделиться

Использование оператора "~" с FlagAttribute и enum
Иногда мы будем использовать атрибут Flag с перечислением для выполнения побитовых манипуляций с перечислением.

 [Flags]
 public enum Colors
 {
    None  = 0,
    Red   = 1,
    Blue  = 2,
    White = 4,
    Black = 8,
    Green = 16,
    All   = 31 //It seems pretty bad...
 }

Обратите внимание, что, значение опциона «Все», которое в enum довольно странное.
Вместо этого мы можем использовать оператор "~" с помеченным enum.

 [Flags]
 public enum Colors
 {
    None  = 0,
    Red   = 1,
    Blue  = 2,
    White = 4,
    Black = 8,
    Green = 16,
    All   = ~0 //much better now. that mean 0xffffffff in default.
 }
15
ответ дан 22 November 2019 в 20:19
поделиться

А как насчет IObservable ?

Практически все знают IEnumerable , но их математическое двойственное кажется неизвестным IObservable . Может быть, потому что это новое в .NET 4.

Вместо извлечения информации (например, перечислимого) он передает информацию подписчикам наблюдаемого.

Вместе с расширениями Rx это изменит способ работы с событиями. Чтобы проиллюстрировать, насколько это мощно, посмотрите очень короткий пример здесь .

20
ответ дан 22 November 2019 в 20:19
поделиться

ОК, это может показаться очевидным, но я хочу упомянуть метод Object.Equals (статический, с двумя аргументами).

Я уверен, что многие люди даже не знают о нем, или забывают о его существовании, а между тем он может очень помочь в некоторых случаях. Например, когда вы хотите сравнить два объекта на равенство, не зная, являются ли они null. Сколько раз вы писали что-то вроде :

if ((x == y) || ((x != null && y != null) && x.Equals(y)))
{
    ...
}

Когда можно просто написать :

if (Object.Equals(x, y))
{
    ...
}

(Object.Equals на самом деле реализовано точно так же, как в первом примере кода)

20
ответ дан 22 November 2019 в 20:19
поделиться

Еще одно замечание по обработчикам событий: вы можете просто создать метод расширения повышения, например так:

public static class EventExtensions {
    public static void Raise<T>(this EventHandler<T> @event, 
                                object sender, T args) where T : EventArgs {
        if(@event!= null) {
            @event(sender, args);
        }
    }
}

Затем вы можете использовать его для создания событий:

public class MyImportantThing {
    public event EventHandler<MyImportantEventEventArgs> SomethingHappens;
    ...
    public void Bleh() {
        SomethingHappens.Raise(this, new MyImportantEventEventArgs { X=true });
    }
}

Этот метод имеет дополнительное преимущество, заключающееся в том, что стандарт кодирования (с использованием EventHandler <> ).

Нет смысла писать одну и ту же функцию снова и снова. Возможно, следующая версия C #, наконец, будет иметь InlineAttribute , который можно будет поместить в метод расширения и заставит компилятор встроить определение метода (что сделает этот способ почти стандартным и самым быстрым).

edit: удалена временная переменная внутри метода расширения на основе комментариев

21
ответ дан 22 November 2019 в 20:19
поделиться

Не совсем скрытый, но полезный. Когда у вас есть перечисление с флагами, вы можете использовать shift-left, чтобы сделать все более понятным. Например,

[Flags]
public enum ErrorTypes {
    None              = 0,
    MissingPassword   = 1 << 0,
    MissingUsername   = 1 << 1,
    PasswordIncorrect = 1 << 2 
}
19
ответ дан 22 November 2019 в 20:19
поделиться

fixed statement

Этот оператор предотвращает перемещение подвижной переменной сборщиком мусора. Fixed также может использоваться для создания буферов фиксированного размера.

Оператор fixed устанавливает указатель на управляемую переменную и "прикалывает" эту переменную во время выполнения оператора.

stackalloc

Оператор stackalloc выделяет блок памяти на стеке.

15
ответ дан 22 November 2019 в 20:19
поделиться

Мне нравится

#if DEBUG
           //Code run in debugging mode

#else
           //Code run in release mode

#endif
7
ответ дан 22 November 2019 в 20:21
поделиться

Работа с перечислениями.

Преобразуйте строку в Перечисление:

enum MyEnum
{
    FirstValue,
    SecondValue,
    ThirdValue
}

string enumValueString = "FirstValue";
MyEnum val = (MyEnum)Enum.Parse(typeof(MyEnum), enumValueString, true)
  • Я использую это для загрузки значения CacheItemPriority в моих приложениях ASP.NET от таблицы настроек в базе данных так, чтобы я мог управлять кэшированием (наряду с другими настройками) динамично, не удаляя приложение.

При сравнении переменных перечисления типа Вы не должны бросать к интервалу:

MyEnum val = MyEnum.SecondValue;
if (val < MyEnum.ThirdValue)
{
    // Do something
}
9
ответ дан 22 November 2019 в 20:21
поделиться

Вот тот, который я недавно обнаружил, который был полезен:

Microsoft.VisualBasic.Logging.FileLogTraceListener

Ссылка MSDN

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

Это "скрыто" потому что в Microsoft. Блок VisualBasic..., но можно использовать его от C# также.

7
ответ дан 22 November 2019 в 20:21
поделиться

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

public class GenericList<T>
{
    private class Node
    {
        //...

        public Node Next;
        public T Data;
    }

    private Node head;

    //...

    public T GetNext()
    {
        T temp = default(T);

        Node current = head;
        if (current != null)
        {
            temp = current.Data;
            current = current.Next;
        }
        return temp;
    }
}

Другой пример здесь

7
ответ дан 22 November 2019 в 20:21
поделиться

Я вполне наслаждаюсь неявными универсальными параметрами на функциях. Например, если Вы имеете:

public void DoStuff<T>(T value);

Вместо того, чтобы назвать его как это:

DoStuff<int>(5);

Вы можете:

DoStuff(5);

И это разработает универсальный тип от типа параметра.

  • Это не работает при вызове метода посредством отражения.
  • Я не забываю иметь некоторые странные проблемы на Моно.
9
ответ дан 22 November 2019 в 20:21
поделиться