Порядок статических конструкторов/инициализаторов в C#

Совсем недавно вы также можете использовать пакет dplyr для этой цели:

library(dplyr)
x %>% 
  group_by(Category) %>% 
  summarise(Frequency = sum(Frequency))

#Source: local data frame [3 x 2]
#
#  Category Frequency
#1    First        30
#2   Second         5
#3    Third        34

Или для нескольких суммарных столбцов (работает с одним столбцом тоже):

x %>% 
  group_by(Category) %>% 
  summarise_each(funs(sum))

Обновление для dplyr> = 0.5: summarise_each было заменено на семейство функций summarise_all, summarise_at и summarise_if в dplyr.

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

mtcars %>% 
  group_by(cyl, gear) %>%                            # multiple group columns
  summarise(max_hp = max(hp), mean_mpg = mean(mpg))  # multiple summary columns

Для получения дополнительной информации, включая оператор %>%, см. введение в dplyr .

19
задан Adam Bellaire 9 October 2008 в 01:15
поделиться

4 ответа

Это, кажется, зависит от последовательности строк. Этот код работы:

static private List<int> a = new List<int>() { 1 };
static private List<int> b = new List<int>() { a[0] };

, в то время как этот код не работает (он бросает NullReferenceException)

static private List<int> a = new List<int>() { b[0] };
static private List<int> b = new List<int>() { 1 };

Так, очевидно, никакие правила для циклической зависимости не существуют. Является странным однако, что компилятор не жалуется...

<час>

РЕДАКТИРОВАНИЕ - Что происходит "через файлы"? Если мы объявляем эти два класса:

public class A {
    public static List<int> a = new List<int>() { B.b[0] };
}
public class B {
    public static List<int> b = new List<int>() { A.a[0] };
}

и попытка получить доступ к ним с этим кодом:

try { Console.WriteLine(B.b); } catch (Exception e) { Console.WriteLine(e.InnerException.Message.); }
try { Console.WriteLine(A.a); } catch (Exception e) { Console.WriteLine(e.InnerException.Message); }
try { Console.WriteLine(B.b); } catch (Exception e) { Console.WriteLine(e.InnerException.Message); }

мы получаем этот вывод:

The type initializer for 'A' threw an exception.
Object reference not set to an instance of an object.
The type initializer for 'A' threw an exception.

Так инициализация B причины исключение в статическом конструкторе A и поле a левых со значением по умолчанию (пустой указатель). С тех пор a null, b не может также быть инициализирован правильно.

, Если у нас нет циклических зависимостей, все хорошо работает.

<час>

РЕДАКТИРОВАНИЕ: На всякий случай Вы не прочитали комментарии, , Jon Skeet обеспечивает очень интересное чтение: различия между статическими конструкторами и вводят инициализаторы .

14
ответ дан 30 November 2019 в 00:23
поделиться

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

static private List<int> a;
static private List<int> b;

static SomeClass()
{
    a = new List<int>() { 0 };
    b = new List<int>() { a[0] };
}

Затем Вы не должны предполагать то, что продолжается, и Вы ясны в своих намерениях.

2
ответ дан 30 November 2019 в 00:23
поделиться

См. раздел 10.4 из спецификации C# для правил здесь:

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

Так, другими словами, в Вашем примере 'b' инициализируется к его состоянию по умолчанию (пустой указатель) и так ссылка на него в инициализаторе законного, но привел бы к NullReferenceException.

Эти правила отличаются от Java (см. раздел 8.3.2.3 из JLS для правил Java о ссылках вперед, которые более строги).

17
ответ дан 30 November 2019 в 00:23
поделиться

Да, Вы были удачливы. C#, кажется, выполняет код в порядке, это появляется в классе.

static private List<int> a = new List<int>() { 0 };
static private List<int> b = new List<int>() { a[0] };

будет работать, но...

static private List<int> b = new List<int>() { a[0] };
static private List<int> a = new List<int>() { 0 };

перестанет работать.

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

static MyClass()
{
  a = new List<int>() { 0 };
  b = new List<int>() { a[0] };
}
0
ответ дан 30 November 2019 в 00:23
поделиться
Другие вопросы по тегам:

Похожие вопросы: