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);
Для получения дополнительной информации см. здесь
Я просто хотел скопировать этот код без комментариев. Итак, уловка состоит в том, чтобы просто нажать кнопку 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 и выбираю прямоугольник и не нужно раскомментировать строки.
Проверьте это.
C # + CLR:
Thread.MemoryBarrier
: Большинство людей не использовали бы его, и в MSDN есть некоторая неточная информация. Но если вы знакомы с тонкостями , тогда вы можете выполнять изящную синхронизацию без блокировок.
volatile, Thread.VolatileRead, Thread.VolatileWrite
: очень мало людей используют их и еще меньше тех, кто понимает все риски, которых они избегают и создают :)
Переменные ThreadStatic
: За последние несколько лет была только одна ситуация, я обнаружил, что переменные ThreadStatic были абсолютно незаменимыми. Например, если вы хотите что-то сделать для всей цепочки вызовов, они очень полезны.
fixed
keyword: It ' скрытое оружие, когда вы хотите сделать доступ к элементам большого массива почти так же быстро, как C ++ (по умолчанию C # применяет связанные проверки, что замедляет работу).
ключевое слово default (typeName)
может использоваться вне общего класса также. Полезно создать пустую копию структуры.
Одной из удобных функций, которые я использую, является DataRow [columnName] .ToString ()
всегда возвращает ненулевое значение. Если значение в базе данных было ПУСТО (NULL), вы получите пустую строку.
Используйте объект Debugger для автоматического прерывания, если вы хотите привлечь внимание разработчика, даже если он / она не включил автоматический прерывание при исключении:
#if DEBUG
if (Debugger.IsAttached)
Debugger.Break();
#endif
using ComplicatedDictionary = Dictionary<int, Dictionary<string, object>>;
ComplicatedDictionary myDictionary = new ComplicatedDictionary();
При отладке вы можете ввести $exception
в окне Watch\QuickWatch\Immediate и получить всю информацию об исключении текущего кадра. Это очень полезно, если у вас включены исключения первого шанса!
Вот новый метод строкового класса в C # 4.0:
String.IsNullOrWhiteSpace(String value)
Пора.
Я прочитал все семь страниц, и мне не хватает этих:
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)
Я попробую придумать еще кое-что ...
{ в любом месте внутри элементов } , { с использованием только фигурных скобок } , { без контроля заявление } .
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
}
Внутри больших, сбивающих с толку или архаичных членов (однако они не должны существовать) это помогает мне предотвратить использование неправильных имен переменных. Разверните материал до более тонких уровней.
. Например, этот код записи 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();
(Также еще одно применение, чтобы держать временную работу вне основной области действия)
Предоставлено Patrik : иногда используется для имитации VB «with- оператор "в C #.
var somePerson = this.GetPerson(); // whatever
{
var p = somePerson;
p.FirstName = "John";
p.LastName = "Doe";
//...
p.City = "Gotham";
}
Для взыскательного программиста.
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 . Надеюсь, это кому-то поможет.
Программисты, переходящие с C / C ++, могут пропустить это:
В C #% (оператор модуля) работает с числами с плавающей запятой!
Анонимные встроенные функции, подобные 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) + "…" : s;
Вы можете «использовать» несколько объектов в одном операторе 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))
{ }
Это отличается от моего.
Легко определить тип, с которым переменная была объявлена (из мой ответ ):
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'
Я обнаружил, что лишь немногие разработчики знают об этой функции.
Если вам нужен метод, который работает с ] переменную типа значения через некоторый интерфейс (реализованный этим типом значения), легко избежать упаковки во время вызова метода.
Пример кода:
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: Интерфейсы, раздел об универсальных шаблонах и интерфейсных ограничениях.
См. также мой ответ на другой вопрос.
ширина в string.Format()
Console.WriteLine("Product: {0,-7} Price: {1,5}", product1, price1);
Console.WriteLine("Product: {0,-7} Price: {1,5}", product2, price2);
производит
typedefs
Кто-то написал, что они пропускают typedefs, но вы можете сделать это так
using ListOfDictionary = System.Collections.Generic.List<System.Collections.Generic.Dictionary<string, string>>;
и объявить это как
ListOfDictionary list = new ListOfDictionary();
Событие AppDomain.UnhandledException Event также является кандидатом на скрытие.
Это событие обеспечивает уведомление о неперехваченных исключениях. Оно позволяет приложению записать информацию об исключении до того, как системный обработчик по умолчанию сообщит об исключении пользователю и завершит работу приложения. Если имеется достаточно информации о состоянии приложения, могут быть предприняты другие действия - например, сохранение данных программы для последующего восстановления. Рекомендуется соблюдать осторожность, поскольку данные программы могут быть повреждены, если исключения не обрабатываются.
Мы видим, что даже на этом сайте многие люди задаются вопросом, почему их приложение не запускается, почему оно разбилось и т.д. Событие AppDomain.UnhandledException
может быть очень полезным для таких случаев, поскольку оно дает возможность хотя бы записать в журнал причину сбоя приложения.
Мой любимый атрибут: InternalsVisibleTo
На уровне сборки вы можете объявить, что ваша сборка может видеть другая сборка. , Для целей тестирования это абсолютно замечательно.
Вставьте это в файл AssemblyInfo.cs или аналогичный, и ваша тестовая сборка получит полный доступ ко всем внутренним компонентам, требующим тестирования.
[assembly: InternalsVisibleTo("MyLibrary.Test, PublicKey=0024...5c042cb")]
Как видите, тестовая сборка должна иметь строгое имя чтобы завоевать доверие к тестируемой сборке.
Доступно в .Net Framework 2.0+, Compact Framework 2.0+ и XNA Framework 1.0+.
Вы можете добавлять и удалять делегатов с меньшим набором текста.
Обычный способ:
handler += new EventHandler(func);
Меньше набора текста:
handler += func;
При определении настраиваемых атрибутов вы можете использовать их с [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 {}
Вы можете ограничить срок службы и, следовательно, объем переменных, используя квадратные скобки {}
.
{
string test2 = "3";
Console.Write(test2);
}
Console.Write(test2); //compile error
test2
живет только в квадратных скобках.
Использование оператора "~" с 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.
}
А как насчет IObservable ?
Практически все знают IEnumerable , но их математическое двойственное кажется неизвестным IObservable . Может быть, потому что это новое в .NET 4.
Вместо извлечения информации (например, перечислимого) он передает информацию подписчикам наблюдаемого.
Вместе с расширениями Rx это изменит способ работы с событиями. Чтобы проиллюстрировать, насколько это мощно, посмотрите очень короткий пример здесь .
ОК, это может показаться очевидным, но я хочу упомянуть метод Object.Equals
(статический, с двумя аргументами).
Я уверен, что многие люди даже не знают о нем, или забывают о его существовании, а между тем он может очень помочь в некоторых случаях. Например, когда вы хотите сравнить два объекта на равенство, не зная, являются ли они null. Сколько раз вы писали что-то вроде :
if ((x == y) || ((x != null && y != null) && x.Equals(y)))
{
...
}
Когда можно просто написать :
if (Object.Equals(x, y))
{
...
}
(Object.Equals
на самом деле реализовано точно так же, как в первом примере кода)
Еще одно замечание по обработчикам событий: вы можете просто создать метод расширения повышения, например так:
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: удалена временная переменная внутри метода расширения на основе комментариев
Не совсем скрытый, но полезный. Когда у вас есть перечисление
с флагами
, вы можете использовать shift-left, чтобы сделать все более понятным. Например,
[Flags]
public enum ErrorTypes {
None = 0,
MissingPassword = 1 << 0,
MissingUsername = 1 << 1,
PasswordIncorrect = 1 << 2
}
fixed statement
Этот оператор предотвращает перемещение подвижной переменной сборщиком мусора. Fixed также может использоваться для создания буферов фиксированного размера.
Оператор fixed устанавливает указатель на управляемую переменную и "прикалывает" эту переменную во время выполнения оператора.
Оператор stackalloc выделяет блок памяти на стеке.
Мне нравится
#if DEBUG
//Code run in debugging mode
#else
//Code run in release mode
#endif
Работа с перечислениями.
Преобразуйте строку в Перечисление:
enum MyEnum
{
FirstValue,
SecondValue,
ThirdValue
}
string enumValueString = "FirstValue";
MyEnum val = (MyEnum)Enum.Parse(typeof(MyEnum), enumValueString, true)
При сравнении переменных перечисления типа Вы не должны бросать к интервалу:
MyEnum val = MyEnum.SecondValue;
if (val < MyEnum.ThirdValue)
{
// Do something
}
Вот тот, который я недавно обнаружил, который был полезен:
Microsoft.VisualBasic.Logging.FileLogTraceListener
Это - реализация TraceListener, которая имеет много функций, таких как файл автоматической записи переворачиваются, для которого я ранее использовал бы пользовательскую платформу журналирования. Хорошая вещь состоит в том, что это - базовая часть.NET и интегрируется с платформой Трассировки, таким образом, его легкое, чтобы взять и сразу использовать.
Это "скрыто" потому что в Microsoft. Блок VisualBasic..., но можно использовать его от C# также.
Использование ключевого слова по умолчанию в универсальном коде для возврата значения по умолчанию для типа.
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;
}
}
Я вполне наслаждаюсь неявными универсальными параметрами на функциях. Например, если Вы имеете:
public void DoStuff<T>(T value);
Вместо того, чтобы назвать его как это:
DoStuff<int>(5);
Вы можете:
DoStuff(5);
И это разработает универсальный тип от типа параметра.