Когда, если когда-нибудь, мы должны использовать константу?

Немного другая проблема, которая вызывает очень похожие сообщения компилятора, зависит от времени жизни объекта, а не для хранения явной ссылки. Примером этого является библиотека ssh2 . При разработке чего-то большего, чем тестовый проект, возникает соблазн попытаться помещать Session и Channel, полученные из этого сеанса рядом друг с другом, в структуру, скрывая детали реализации от пользователя. Однако обратите внимание, что определение Channel имеет время жизни 'sess в аннотации типа, а Session - нет.

вызывает аналогичные ошибки компилятора, связанные со временем жизни.

Один из способов его решения очень простым образом - объявить Session снаружи в вызывающем, а затем для аннотации ссылки в структуре со временем жизни, подобный ответ в , этот пост Форума пользователя Rust говорит об одной и той же проблеме при инкапсуляции SFTP. Это не будет выглядеть элегантно и может не всегда применяться - потому что теперь у вас есть два объекта для работы, а не тот, который вам нужен!

Выключает арендованный ящик или owning_ref crate из другого ответа также являются решениями для этой проблемы. Рассмотрим owning_ref, который имеет специальный объект для этой цели: OwningHandle . Чтобы избежать перемещения основного объекта, мы выделяем его в куче, используя Box, что дает нам следующее возможное решение:

use ssh2::{Channel, Error, Session};
use std::net::TcpStream;

use owning_ref::OwningHandle;

struct DeviceSSHConnection {
    tcp: TcpStream,
    channel: OwningHandle, Box>>,
}

impl DeviceSSHConnection {
    fn new(targ: &str, c_user: &str, c_pass: &str) -> Self {
        use std::net::TcpStream;
        let mut session = Session::new().unwrap();
        let mut tcp = TcpStream::connect(targ).unwrap();

        session.handshake(&tcp).unwrap();
        session.set_timeout(5000);
        session.userauth_password(c_user, c_pass).unwrap();

        let mut sess = Box::new(session);
        let mut oref = OwningHandle::new_with_fn(
            sess,
            unsafe { |x| Box::new((*x).channel_session().unwrap()) },
        );

        oref.shell().unwrap();
        let ret = DeviceSSHConnection {
            tcp: tcp,
            channel: oref,
        };
        ret
    }
}

. Результатом этого кода является то, что мы не можем использовать Session, но он сохраняется вместе с Channel, который мы будем использовать. Поскольку OwningHandle вызывает раздел Box, который разделяет Channel, когда он хранится в структуре, мы называем его как таковой. ПРИМЕЧАНИЕ. Это только мое понимание. У меня есть подозрение, что это может быть неверно, поскольку оно, по-видимому, очень близко к обсуждению OwningHandle небезопасности .

. Любопытная деталь здесь заключается в том, что Session логически имеет аналогичную связь с TcpStream, поскольку Channel имеет значение Session, но его собственность не принимается и нет аннотаций типа вокруг так. Вместо этого пользователь должен позаботиться об этом, поскольку в документации к методу рукопожатия говорится:

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

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

blockquote>

Таким образом, использование TcpStream полностью зависит от программиста, чтобы обеспечить правильность кода. С OwningHandle внимание к тому, где происходит «опасная магия», выполняется с помощью блока unsafe {}.

Дальнейшее и более высокоуровневое обсуждение этой проблемы находится в этом Rust User's Forum - который включает в себя другой пример и его решение с использованием ящика для аренды, который не содержит небезопасных блоков.

26
задан Frederick The Fool 17 February 2009 в 04:46
поделиться

9 ответов

Я полагаю, что единственное время "константа" является подходящим, когда существует спецификация, которую Вы кодируете против этого, более длительно, чем программа, которую Вы пишете. Например, при реализации протокола HTTP имение участника константы для "ДОБИРАЕТСЯ", является соответствующим, потому что это никогда не будет изменяться, и клиенты могут, конечно, твердый код, что в их скомпилированные приложения, не волнуясь, что необходимо будет изменить значение позже.

, Если существует шанс вообще, необходимо изменить значение в будущих версиях, не используйте константу

, О! И никогда не предполагайте, что константа быстрее, чем поле только для чтения, если Вы не измерили ее. Существует оптимизация JIT, которая может сделать его так, это - на самом деле точно то же.

30
ответ дан Andrew Arnott 15 October 2019 в 07:45
поделиться

Константа по сравнению с только для чтения :

А быстрое резюме на различиях между 'константой' и 'только для чтения' в C#: 'константа':

  • не Может быть статичным.
  • Значение оценено по телефону время компиляции.
  • Initiailized в объявлении только.

'только для чтения':

  • Может быть или уровень экземпляра или статичный.
  • Значение оценено по телефону время выполнения.
  • Может быть инициализирован в объявлении или кодом в конструкторе.

Исправление: вышеупомянутая константа состояний не может быть статичной. Это - неправильное употребление. Им нельзя было применить статическое ключевое слово, потому что они уже статичны.

, Таким образом, Вы используете константу для статических объектов, которые Вы хотите оцененный во время компиляции.

15
ответ дан cletus 15 October 2019 в 07:45
поделиться

Можно использовать значение константы в качестве случая в операторе переключения, fwiw.

4
ответ дан ChrisW 15 October 2019 в 07:45
поделиться

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

В некотором смысле, только для чтения константа во время выполнения & константа является постоянной величиной времени компиляции.

РЕДАКТИРОВАНИЕ: при рассмотрении некоторого кода с помощью www.koders.com Вы найдете, что существует использование только для чтения, где константа, возможно, использовалась. Я думаю, причина позади этого могла быть этим, является модифицируемым в конструкторе (в случае необходимости). В случае (особенно общедоступной) константы у Вас есть шанс повреждения клиента, кодозависимого на Вашем коде.

3
ответ дан shahkalpesh 15 October 2019 в 07:45
поделиться

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

я предпочитаю только для чтения для вещей, которые могли потенциально изменение. Таким образом, я только должен перекомпилировать один dll, если изменение происходит. Исключение к этому эмпирическому правилу - то, если переменная является частной/защищать/дружественной к своему собственному блоку. В тех случаях безопасно использовать константу

3
ответ дан Daniel Auger 15 October 2019 в 07:45
поделиться

константа не может использоваться для классов или структур (за исключением строковых констант и пустого указателя, как г-н Skeet указал), только для типов значения, и получены доступ как статические поля. Значение константы установлено во время компиляции и должно быть установлено, когда оно объявляется.

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

Вот хорошая страница для обзора константы, и статических ключевых слов только для чтения.

2
ответ дан Logan5 15 October 2019 в 07:45
поделиться

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

1
ответ дан 15 October 2019 в 07:45
поделиться

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

0
ответ дан JoelFan 15 October 2019 в 07:45
поделиться

Хорошее использование константы для ключей пар ключ/значение. Например, при тихом использовании AppSetting (вместо ApplicationSettings), он действительно не имеет смысла к загрузка название ключа к параметру конфигурации. Если это используется в нескольких местах, засуньте Ключ в константе

0
ответ дан Greg Ogle 15 October 2019 в 07:45
поделиться
Другие вопросы по тегам:

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