скрыть параметрический конструктор на struct

22

Можно ли скрыть конструктор без параметров от пользователя в c #

Я хочу заставить их всегда использовать конструктор с параметрами

например. этот класс позиции

public struct Position
{
    private readonly int _xposn;
    private readonly int _yposn;

    public int Xposn
    {
        get { return _xposn; }
    }

    public int Yposn
    {
        get { return _yposn; }
    }

    public Position(int xposn, int yposn)
    {
        _xposn = xposn;
        _yposn = yposn;
    }        
}

Я хочу, чтобы пользователи могли обновлять позицию, задавая координаты x и y

Однако безпараллельный конструктор ВСЕГДА доступен

Я не могу сделать это частным. Или даже определить его как общедоступный

Я прочитал это Почему я не могу определить значение по умолчанию конструктор для структуры в .NET?

, но он действительно не помогает

Если это невозможно - что является лучшим способом определить, есть ли значение, которое я передаю, значения?

Объяснение каждого поля свойств? Есть ли более гладкий способ?

спасибо

    
задан ChrisCa 11.02.2009 в 04:40
источник

4 ответа

21

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

Вы можете создать частный бездонный конструктор для struct , но не на C #. Однако, даже если вы это сделаете, это не поможет - потому что вы можете легко обойти это:

MyStruct[] tmp = new MyStruct[1];
MyStruct gotcha = tmp[0];

Это будет значение по умолчанию MyStruct - значение «all zeroes» - без вызова конструктора.

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

ответ дан Jon Skeet 11.02.2009 в 08:33
  • Я рассматриваю это как проблему юзабилити больше, чем что-либо еще. Конструктор по умолчанию может создать допустимый объект, но для многих структур это не то, что пользователь хочет или ожидает. Тем не менее некоторые люди будут использовать этот конструктор по умолчанию только потому, что это первый вариант, который дает их IDE. И тогда у них будут путаные ошибки, вызванные обнуленными структурами, которые должны были быть заполнены данными, или они будут тратить время на попытки выяснить, почему они не могут устанавливать свойства в неизменяемой структуре. С точки зрения API-дизайна мне хотелось бы скрыть конструктор по умолчанию. –  MB. 12.10.2011 в 18:29
  • +1 @MB. Частный конструктор по умолчанию поможет, даже если определенный «дурак» может обойти его. Как соль C ++, я думаю, что это личное, как подсказка, чтобы не стрелять в ногу, всегда есть работа с помощью указателей. И семантику массива можно позаботиться, просто не позволяя создавать массивы таких структур. –  Adrian Ratnapala 27.02.2014 в 13:58
  • @roryapL Исправлено, спасибо. –  Jon Skeet 06.05.2016 в 22:17
  • Эй, Джон только одно о параметризованных конструкторах struct. Если вы можете проверить его, как я его где-то читал. Параметрированный конструктор для структуры по-прежнему вызывает стандартный конструктор без параметров (который он предопределяет для структуры в FCL) как первое в своем исполнении. Я считаю, что для достижения такого поведения существует трюк компилятора. –  RBT 19.10.2016 в 04:03
  • @RBT: В C # 6 есть изменения вокруг этого в отношении того, нужно ли это делать явно или нет для автоматически реализованных свойств для работы, но помимо этого я не думаю, что это легко наблюдать, если вы не добавите пользовательский конструктор без параметров через IL ... мой опыт в том, что это не всегда называется, но я подозреваю, что он вызван из параметризованных конструкторов ... Мне нужно было бы проверить, но это не то, что я когда-либо видел в реальном коде так или иначе. –  Jon Skeet 19.10.2016 в 08:00
4

Невозможно скрыть это. Структуры не могут переопределить нулевой конструктор arg, поэтому его видимость не может быть переопределена.

    
ответ дан DavidN 11.02.2009 в 04:47
  • Ну, .NET позволяет вам предоставить настраиваемый конструктор без параметров, но вы не можете сделать это непосредственно на C #, и это никоим образом не поможет, так как вы можете легко обойти его. –  Jon Skeet 11.02.2009 в 08:35
2

Ну, структура - это буквально объявление о том, как будет сидеть память.

Даже когда вы используете объект, объявляется указатель объектов, независимо от того, является ли он нулевым.

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

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

struct point
{
   int xpos;
   int ypos;
}

Имейте google для неизменяемых объектов, это похоже на то, что вы после. Я считаю, что они хотят добавить эту функцию (но не в C # 4) к самому языку, потому что это общее требование. Существует ли конкретная потребность в структуре?

    
ответ дан Spence 11.02.2009 в 04:47
  • что вы подразумеваете под этим? использовать статический анализ, чтобы убедиться в том, что он инициализирован, вы имеете в виду, что каждое поле имеет значение? –  ChrisCa 11.02.2009 в 04:49
  • Вы можете запустить инструмент статического анализа с правилом, чтобы гарантировать, что в любое время кто-то использует тип в своем коде, чтобы эти два значения были инициализированы. или вы могли бы сделать некоторые причудливые работы, объявив его как объект для проверки, а затем перейдите к структуре в сборке релизов. –  Spence 11.02.2009 в 04:52
1

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

Из руководства по структурированию в MSDN:

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

Из спецификации C # в MSDN:

11.3 Различия в классе и структуре

Структуры отличаются от классов несколькими важными способами:

  • Структуры - это типы значений (раздел 11.3.1).
  • Все типы структур неявно наследуют из класса System.ValueType (Раздел 11.3.2). Назначение переменная типа struct создает копия присваиваемого значения (Раздел 11.3.3).
  • Значением по умолчанию для структуры является значение, созданное установкой всей стоимости введите поля по умолчанию и все поля ссылочного типа равны нулю (Раздел 11.3.4). Бокс и операции распаковки используются для конвертировать между типом структуры и объект (раздел 11.3.5).
  • Смысл этого отличается для структур (раздел 11.3.6).
  • Объявление полей экземпляра для структура не допускается включать переменные инициализаторы (раздел 11.3.7).
  • Структуре не разрешено объявлять конструктор без параметров (Раздел 11.3.8).
  • Строке не разрешено объявлять деструктор (раздел 11.3.9).
ответ дан Ryan 11.02.2009 в 06:42