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

Не уверен, что это уже упоминалось или нет (11 страниц!!)

Но атрибут OptionalField для классов просто замечателен, когда вы версионируете классы/объекты, которые будут сериализованы.

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

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

ИСПРАВЛЕНО / Сила указателей в C # - эта тема слишком большая, но я просто обрисую простые вещи.

В C у нас была возможность загрузки структуры, как ...

struct cType{
   char type[4];
   int  size;
   char name[50];
   char email[100];
}

cType myType;
fread(file, &mType, sizeof(mType));

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

[Layout(LayoutKind.Sequential, Pack=1)]
public unsafe class CType{
    public fixed byte type[4];
    public int size;
    public fixed byte name[50];
    public fixed byte email[100];
}

Метод 1 (чтение из обычного потока в байтовый буфер и отображение байтового массива в отдельные байты структуры)

CType mType = new CType();
byte[] buffer = new byte[Marshal.SizeOf(CType)];
stream.Read(buffer,0,buffer.Length);
// you can map your buffer back to your struct...
fixed(CType* sp = &mType)
{
    byte* bsp = (byte*) sp;
    fixed(byte* bp = &buffer)
    {
         for(int i=0;i<buffer.Length;i++)
         {
             (*bsp) = (*bp);
             bsp++;bp++;
         }
    }
}

Метод 2, вы можете сопоставить Win32 User32.dll ReadFile с прямым чтением байтов ...

CType mType = new CType();
fixed(CType* p = &mType)
{
    User32.ReadFile(fileHandle, (byte*) p, Marshal.SizeOf(mType),0);
}
5
ответ дан 22 November 2019 в 20:21
поделиться

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

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

Если у вас есть текстовое поле поиска на панели инструментов Visual Studio, вы можете ввести "> of Program.cs", чтобы открыть файл Program.cs

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

Возможность создания экземпляра типа на основе такого универсального параметра, как этот

new T ();

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

Маркетинговые события как несериализуемые:

[field:NonSerializable]
public event SomeDelegate SomeEvent;
4
ответ дан 22 November 2019 в 20:21
поделиться

Общие ограничения:

 //Constructor constraint, T has a default empty constructor
class Node<K,T> where T : new() 
{
}

//Reference\Value Type constraints
//T is a struct
public class MyClass<T> where T : struct 

{...}

//T is a reference type
public class MyClass<T> where T : class 

{...}

public class MyClass<T> where T : SomeBaseClass, ISomeInterface 

{...}
4
ответ дан 22 November 2019 в 20:21
поделиться

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

// defines a descriptive name for a complexed data type
using MyDomainClassList = System.Collections.Generic.List<
  MyProjectNameSpace.MyDomainClass>;

....


MyDomainClassList myList = new MyDomainClassList();
/* instead of 
List<MyDomainClass> myList = new List<MyDomainClass>();
*/

Это также очень удобно для обслуживания кода. Если вам нужно изменить имя класса, вам нужно изменить только одно место. Другой пример:

using FloatValue  = float; // you only need to change it once to decimal, double...

....
FloatValue val1;
...
5
ответ дан 22 November 2019 в 20:21
поделиться

Лямбда с нулевым параметром

()=>Console.ReadLine()
5
ответ дан 22 November 2019 в 20:21
поделиться

Я этого не видел:

for (;;);

То же, что

while (true) ;
5
ответ дан 22 November 2019 в 20:21
поделиться

Недавно я узнал, что вы все еще можете вызывать методов для значения, допускающего значение NULL ....

Оказывается, что, когда у вас есть значение, допускающее значение NULL :

decimal? MyValue = null;

где вы могли подумать, что вам нужно написать:

MyValue == null ? null : MyValue .ToString()

вместо этого вы можете написать:

MyValue.ToString()

Я знал, что могу вызвать MyValue.HasValue и MyValue.Value ... но это не полностью щелкните, чтобы я мог вызвать ToString ().

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

Это не скомпилируется:

namespace ns
{
    class Class1
    {
        Nullable<int> a;
    }
}

Не удалось найти тип или имя пространства имен 'Nullable' (отсутствует ли у вас директива using или ссылка на сборку?) <- отсутствует ' using System; '

Но

namespace ns
{
    class Class1
    {
        int? a;
    }
}

компилируется! (.NET 2.0).

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

Прошу прощения, если этот был упомянут, но я часто его использую.

Надстройка для Visual Studio была разработана Алексом Пападимулисом. Он используется для вставки обычного текста в виде строки, конструктора строк, комментария или региона.

http://weblogs.asp.net/alex_papadimoulis/archive/2004/05/25/Smart-Paster-1.1-Add-In-- -StringBuilder-and-Better-C_2300_-Handling.aspx

В этом плагине (я также не знаю, упоминалось ли об этом) я заметил, что строки вставляются с префиксом строкового литерала:

@

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

Например,

string s = "A line of text" + Environment.NewLine + "Another with a \"quote\"!!";

может быть выражено как

string s = @"A line of text 
Another with a ""quote""!!";
5
ответ дан 22 November 2019 в 20:21
поделиться

Мне нравится EditorBrowsableAttribute . Он позволяет вам контролировать, отображается ли метод / свойство в Intellisense. Вы можете установить значения «Всегда», «Расширенный» или «Никогда».

Из MSDN ...

Примечания

Атрибут EditorBrowsableAttribute - это подсказка для дизайнера, указывающая, следует ли отображать свойство или метод. Вы можете использовать этот тип в визуальном конструкторе или текстовом редакторе, чтобы определить, что видно пользователю. Например, механизм IntelliSense в Visual Studio использует этот атрибут, чтобы определить, следует ли отображать свойство или метод.

В Visual C # вы можете управлять отображением дополнительных свойств в IntelliSense и в окне свойств с помощью параметра «Скрыть расширенные члены» в разделе «Инструменты». | Опции | Текстовый редактор | С #. Соответствующее EditorBrowsableState - Advanced.

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

__ arglist as well

[DllImport("msvcrt40.dll")]
public static extern int printf(string format, __arglist);

static void Main(string[] args)
{
   printf("Hello %s!\n", __arglist("Bart"));
}
5
ответ дан 22 November 2019 в 20:21
поделиться

Помощники делегатов от Action и Func в сочетании с лямбда-методами. Я использую их для простых моделей, которые требуют участия делегата для улучшения читабельности. Например, простым шаблоном кэширования будет проверка наличия запрашиваемого объекта в кэше. Если он действительно существует: верните кэшируемый объект. Если он не существует, сгенерируйте новый объект, кэшируйте новый объект и верните новый объект. Вместо того, чтобы писать этот код 1000 раз для каждого объекта, который я могу хранить/получать из кэша, я могу написать простой шаблонный метод, подобный этому...

private static T CachePattern<T>(string key, Func<T> create) where T : class
{
    if (cache[key] == null)
    {
        cache.Add(key, create());
    }

    return cache[key] as T;
}

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

public static IUser CurrentUser
{
    get
    {
        return CachePattern<IUser>("CurrentUserKey", () => repository.NewUpUser());
    }
}

Теперь простые "повседневные" шаблоны кода можно написать один раз и намного проще использовать IMHO. Мне не нужно идти писать тип делегата и выяснять, как я хочу реализовать обратный вызов и т.д. Если я могу написать его за 10 секунд, то я гораздо менее склонен прибегать к вырезанию/вставке простых шаблонов кода, будь то ленивая инициализация и некоторые другие примеры, показанные выше...

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

Разрешены пустые блоки с фигурными скобками.

Вы можете написать такой код.

{
    service.DoTonsOfWork(args);
}

Это полезно, когда вы хотите попробовать что-то без , используя или try ... finally , которые вы уже написали.

//using(var scope = new TransactionScope)
{
    service.DoTonsOfWork(args);
}
5
ответ дан 22 November 2019 в 20:21
поделиться

Nullable.GetValueOrDefault?

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

How about Expression Trees? They are the heart of LINQ and allow for defered execution:

Taken from David Hayden's blog:

In C# 3.0, you can define a delegate as follows using a lambda expression:

Func<int,int> f = x => x + 1;

This delegate is compiled into executable code in your application and can be called as such:

var three = f(2); // 2 + 1

The code works as you would expect. Nothing fancy here.

Expression Trees

When you define the delegate as an Expression Tree by using System.Query.Expression:

Expression<Func<int,int>> expression = x => x + 1;

The delegate is no longer compiled into executable code, but compiled as data that can be converted and compiled into the original delegate.

To actually use the delegate represented as an Expression Tree in your application, you would have to compile and invoke it in your application:

var originalDelegate = expression.Compile();

var three = originalDelegate.Invoke(2);
4
ответ дан 22 November 2019 в 20:21
поделиться

Ну ... Не используйте его , но многие люди не знают, что C # поддерживает злой goto :)

static void Example()
{
    int i = 0;
top:
    Console.WriteLine(i.ToString());
    if (i == 0)
    {
        i++;
        goto top;
    }
}
3
ответ дан 22 November 2019 в 20:21
поделиться

Определенно типы Func <> при использовании с лямбда-выражениями операторов в .NET 3.5. Они позволяют настраивать функции и могут быть большим подспорьем в предложении настраиваемых пользователем объектов без их подкласса или обращения к какой-либо ограниченной системе, такой как отслеживание переменной, в которой указывается, какую кнопку или клавишу пользователь хочет отслеживать. Кроме того, они могут вызываться как обычные методы и назначаться как переменные. Единственный недостаток, о котором я могу думать, - это то, что вы ограничены 5 аргументами! Хотя к этому моменту вы, возможно, захотите рассмотреть другое решение ... Изменить: предоставить несколько примеров.

...
public Func<InputHelper, float> _horizontalCameraMovement = (InputHelper input) => 
{
    return (input.LeftStickPosition.X * _moveRate) * _zoom;
}
public Func<InputHelper, float> _verticalCameraMovement = (InputHelper input) => 
{
    return (-input.LeftStickPosition.Y * _moveRate) * _zoom;
}
...
public void Update(InputHelper input)
{
    ...
    position += new Vector2(_horizontalCameraMovement(input), _verticalCameraMovement(input));
    ...
}

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

private int foo;
public int FooProperty {
    get
    {
        if (_onFooGotten() == true)
            return _foo;
    }
    set
    {
        if (onFooSet() == true)
            _foo = value;
    }
}
...
public Func<bool> _onFooGotten = () => 
{
    //do whatever...
    return true;
}
public Func<bool> _onFooSet = () =>
{
    //do whatever...
    return true;
}

Это не лучший пример (так как я еще не исследовал это использование), но он показывает пример использования лямбда-функции для быстрого повышения событий без хлопоты делегатов. Изменить: подумал о другом. Nullables! Самая близкая вещь C # к необязательным параметрам.

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

A few from me - make of them what you will.

The attribute:

[assembly::InternalsVisibleTo("SomeAssembly")]

Allows you to expose out the internal methods/properties or data from your assembly to another assembly called 'SomeAssembly'. All protected/private stuff remains hidden.


Static constructors ( otherwise called 'Type Constructor' )

public MyClass
{
  public static MyClass()
  {
     // type init goes here
  }
  ......
}  

The keyword internal. So useful in so many ways.

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

Если вы пытаетесь создать строку с разделителями-запятыми из списка элементов:

string[] itemList = { "Example 1", "Example 2", "Example 3" };
CommaDelimitedStringCollection commaStr = new CommaDelimitedStringCollection();
commaStr.AddRange(itemList);
//outputs Example 1,Example 2,Example 3

Посмотрите здесь для другого примера.

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

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

Как только вы полностью поймете C #, пора углубиться в это, чтобы понять основы инфраструктуры общего языка . Архитектура и основы C #.

Я встречал множество программистов, которые не знали разницы между объектом и ValueType, за исключением присущих им ограничений.

Ознакомьтесь с этими двумя документами, и вы никогда не станете таким человеком.

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

Generics и Curious-Recurring Template Pattern действительно помогают с объявлениями некоторых статических методов / свойств.

Предположим, вы строите иерархию классов:

class Base
{
}

class Foo: Base
{
}

class Bar: Base
{
}

Теперь, вы хотите объявить статические методы для своих типов, которые должны принимать параметры (или возвращаемые значения) одного типа или статические свойства одного типа. Например, вы хотите:

class Base
{
    public static Base Get()
    {
        // Return a suitable Base.
    }
}

class Foo: Base
{
    public static Foo Get()
    {
        // Return a suitable Foo.
    }
}

class Bar: Base
{
    public static Bar Get()
    {
        // Return a suitable Bar.
    }
}

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

class Base<T> where T: Base<T>
{
    public static T Get<T>()
    {
        // Return a suitable T.
    }
}

, а вы Foo и Bar как:

class Foo: Base<Foo>
{
}

class Bar: Base<Bar>
{
}

This путь, они автоматически получат свои копии статических методов.

Это также творит чудеса, инкапсулируя шаблон Синглтон в базовый класс (я знаю, что приведенный ниже код не является потокобезопасным , это просто для демонстрации одной мысли):

public class Singleton<T> where T: Singleton<T>, new()
{
  public static T Instance { get; private set; }

  static Singleton<T>()
  {
    Instance = new T();
  }
}

Я понимаю, что это заставляет вас иметь общедоступный конструктор без параметров в вашем синглтон-подклассе, но нет способа избежать этого во время компиляции без , где T: protected new ( ) конструкция; однако можно использовать отражение для вызова защищенного / закрытого конструктора подкласса без параметров во время выполнения для достижения этой цели.

public class Singleton<T> where T: Singleton<T>, new()
{
  public static T Instance { get; private set; }

  static Singleton<T>()
  {
    Instance = new T();
  }
}

Я понимаю, что это вынуждает вас иметь общедоступный конструктор без параметров в вашем синглтон-подклассе, но нет способа избежать этого во время компиляции без конструкции where T: protected new () ; однако можно использовать отражение для вызова защищенного / закрытого конструктора подкласса без параметров во время выполнения для достижения этой цели.

public class Singleton<T> where T: Singleton<T>, new()
{
  public static T Instance { get; private set; }

  static Singleton<T>()
  {
    Instance = new T();
  }
}

Я понимаю, что это вынуждает вас иметь общедоступный конструктор без параметров в вашем синглтон-подклассе, но нет способа избежать этого во время компиляции без конструкции where T: protected new () ; однако можно использовать отражение для вызова защищенного / закрытого конструктора подкласса без параметров во время выполнения для достижения этой цели.

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

Вы можете использовать функцию appendTo (которая добавляет в конец элемента):

$("#source").appendTo("#destination");

В качестве альтернативы вы можете использовать функцию prependTo (которая добавляет к начало элемента):

$("#source").prependTo("#destination");

Пример:

 $ ("# appendTo"). click (function () {$ ("# moveMeIntoMain"). appendTo ($ ("# main"));}) ; $ ("# prependTo"). click (function () {$ ("
если вы не хотите, чтобы к ним обращались напрямую, это усложняет задачу: 

[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
    private DataController p_dataSources;
3
ответ дан 22 November 2019 в 20:21
поделиться

Сначала - DebuggerTypeProxy .

[DebuggerTypeProxy(typeof(HashtableDebugView))]
class MyHashtable : Hashtable
{
    private const string TestString = 
        "This should not appear in the debug window.";

    internal class HashtableDebugView
    {
        private Hashtable hashtable;
        public const string TestStringProxy = 
            "This should appear in the debug window.";

        // The constructor for the type proxy class must have a 
        // constructor that takes the target type as a parameter.
        public HashtableDebugView(Hashtable hashtable)
        {
            this.hashtable = hashtable;
        }
    }
}

Во второй:

ICustomTypeDescriptor

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

I love abusing the fact that static templated classes don't share their static members.

Here's a threadsafe (at creation time) and cheap substitute to any Dictionary when the Type instance is known at compile-time.

public static class MyCachedData<T>{
    static readonly CachedData Value;
    static MyCachedData(){
       Value=// Heavy computation, such as baking IL code or doing lots of reflection on a type
    }
}

Cheers, Florian

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

Следующий не скрыт, но совершенно неявный. Я не знаю, публиковались ли здесь примеры, подобные следующему, и не вижу, есть ли какие-то преимущества (возможно, их нет), но я постараюсь показать «странный» код. В следующем примере моделируется для оператора через функторы в C # (делегаты / анонимные делегаты [лямбда-выражения]) и замыкания. Также моделируются другие операторы потока, такие как if , if / else , while и do / whle , но я не уверен для переключателя (возможно, мне лень :)). Я немного сжал исходный код примера, чтобы сделать его более понятным.

private static readonly Action EmptyAction = () => { };
private static readonly Func<bool> EmptyCondition = () => { return true; };

private sealed class BreakStatementException : Exception { }
private sealed class ContinueStatementException : Exception { }
private static void Break() { throw new BreakStatementException(); }
private static void Continue() { throw new ContinueStatementException(); }

private static void For(Action init, Func<bool> condition, Action postBlock, Action statement) {
    init = init ?? EmptyAction;
    condition = condition ?? EmptyCondition;
    postBlock = postBlock ?? EmptyAction;
    statement = statement ?? EmptyAction;
    for ( init(); condition(); postBlock() ) {
        try {
            statement();
        } catch ( BreakStatementException ) {
            break;
        } catch ( ContinueStatementException ) {
            continue;
        }
    }
}

private static void Main() {
    int i = 0; // avoiding error "Use of unassigned local variable 'i'" if not using `for` init block
    For(() => i = 0, () => i < 10, () => i++,
        () => {
            if ( i == 5 )
                Continue();
            Console.WriteLine(i);
        }
    );
}

Если я не ошибаюсь, этот подход довольно похож на практику функционального программирования. Я прав?

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

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

При использовании перечисления

enum Country
{
    UnitedKingdom, 
    UnitedStates,
    UnitedArabEmirates,
}

:

public static void PrintEnumAsString( Country country )
{
    Console.Writeline( country.ToString() );
}

напечатает имя значения перечисления в виде строки, например, «UnitedKingdom»

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