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);
Для получения дополнительной информации см. здесь
Не уверен, что это уже упоминалось или нет (11 страниц!!)
Но атрибут OptionalField
для классов просто замечателен, когда вы версионируете классы/объекты, которые будут сериализованы.
http://msdn.microsoft.com/en-us/library/ms229752(VS.80).aspx
ИСПРАВЛЕНО / Сила указателей в 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);
}
InternalsVisibleToAttribute указывает, что типы, которые обычно видимы только внутри текущей сборки, видны другой сборке. Статья о msdn
Если у вас есть текстовое поле поиска на панели инструментов Visual Studio, вы можете ввести "> of Program.cs", чтобы открыть файл Program.cs
Возможность создания экземпляра типа на основе такого универсального параметра, как этот
new T ();
Маркетинговые события как несериализуемые:
[field:NonSerializable]
public event SomeDelegate SomeEvent;
Общие ограничения:
//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
{...}
Мне нравится использовать , используя для переименования некоторых классов для облегчения чтения, например:
// 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;
...
Я этого не видел:
for (;;);
То же, что
while (true) ;
Недавно я узнал, что вы все еще можете вызывать методов для значения, допускающего значение NULL ....
Оказывается, что, когда у вас есть значение, допускающее значение NULL :
decimal? MyValue = null;
где вы могли подумать, что вам нужно написать:
MyValue == null ? null : MyValue .ToString()
вместо этого вы можете написать:
MyValue.ToString()
Я знал, что могу вызвать MyValue.HasValue и MyValue.Value ... но это не полностью щелкните, чтобы я мог вызвать ToString ().
Это не скомпилируется:
namespace ns
{
class Class1
{
Nullable<int> a;
}
}
Не удалось найти тип или имя пространства имен 'Nullable' (отсутствует ли у вас директива using или ссылка на сборку?) <- отсутствует ' using System;
'
Но
namespace ns
{
class Class1
{
int? a;
}
}
компилируется! (.NET 2.0).
Прошу прощения, если этот был упомянут, но я часто его использую.
Надстройка для Visual Studio была разработана Алексом Пападимулисом. Он используется для вставки обычного текста в виде строки, конструктора строк, комментария или региона.
В этом плагине (я также не знаю, упоминалось ли об этом) я заметил, что строки вставляются с префиксом строкового литерала:
@
Я знал об этом , но я не знал об использовании двойных кавычек внутри литерала, чтобы избежать кавычек.
Например,
string s = "A line of text" + Environment.NewLine + "Another with a \"quote\"!!";
может быть выражено как
string s = @"A line of text
Another with a ""quote""!!";
Мне нравится EditorBrowsableAttribute . Он позволяет вам контролировать, отображается ли метод / свойство в Intellisense. Вы можете установить значения «Всегда», «Расширенный» или «Никогда».
Из MSDN ...
Примечания
Атрибут EditorBrowsableAttribute - это подсказка для дизайнера, указывающая, следует ли отображать свойство или метод. Вы можете использовать этот тип в визуальном конструкторе или текстовом редакторе, чтобы определить, что видно пользователю. Например, механизм IntelliSense в Visual Studio использует этот атрибут, чтобы определить, следует ли отображать свойство или метод.
В Visual C # вы можете управлять отображением дополнительных свойств в IntelliSense и в окне свойств с помощью параметра «Скрыть расширенные члены» в разделе «Инструменты». | Опции | Текстовый редактор | С #. Соответствующее EditorBrowsableState - Advanced.
__ 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"));
}
Помощники делегатов от 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 секунд, то я гораздо менее склонен прибегать к вырезанию/вставке простых шаблонов кода, будь то ленивая инициализация и некоторые другие примеры, показанные выше...
.Разрешены пустые блоки с фигурными скобками.
Вы можете написать такой код.
{
service.DoTonsOfWork(args);
}
Это полезно, когда вы хотите попробовать что-то без , используя
или try ... finally
, которые вы уже написали.
//using(var scope = new TransactionScope)
{
service.DoTonsOfWork(args);
}
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);
Ну ... Не используйте его , но многие люди не знают, что C # поддерживает злой goto :)
static void Example()
{
int i = 0;
top:
Console.WriteLine(i.ToString());
if (i == 0)
{
i++;
goto top;
}
}
Определенно типы 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 # к необязательным параметрам.
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.
Если вы пытаетесь создать строку с разделителями-запятыми из списка элементов:
string[] itemList = { "Example 1", "Example 2", "Example 3" };
CommaDelimitedStringCollection commaStr = new CommaDelimitedStringCollection();
commaStr.AddRange(itemList);
//outputs Example 1,Example 2,Example 3
Посмотрите здесь для другого примера.
Многое из этого уже объяснено в стандарте . Это хорошее чтение для любого новичка, а также для эксперта, его много для чтения, но это официальный стандарт, и он наполнен сочными деталями.
Как только вы полностью поймете C #, пора углубиться в это, чтобы понять основы инфраструктуры общего языка . Архитектура и основы C #.
Я встречал множество программистов, которые не знали разницы между объектом и ValueType, за исключением присущих им ограничений.
Ознакомьтесь с этими двумя документами, и вы никогда не станете таким человеком.
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 ()
; однако можно использовать отражение для вызова защищенного / закрытого конструктора подкласса без параметров во время выполнения для достижения этой цели.
Вы можете использовать функцию 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;
Сначала - 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;
}
}
}
Во второй:
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
Следующий не скрыт, но совершенно неявный. Я не знаю, публиковались ли здесь примеры, подобные следующему, и не вижу, есть ли какие-то преимущества (возможно, их нет), но я постараюсь показать «странный» код. В следующем примере моделируется для оператора
через функторы в 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);
}
);
}
Если я не ошибаюсь, этот подход довольно похож на практику функционального программирования. Я прав?
Преобразование значений перечисления в строковое значение
При использовании перечисления
enum Country
{
UnitedKingdom,
UnitedStates,
UnitedArabEmirates,
}
:
public static void PrintEnumAsString( Country country )
{
Console.Writeline( country.ToString() );
}
напечатает имя значения перечисления в виде строки, например, «UnitedKingdom»