blockquote>
+
для следующего брата. Есть ли эквивалент для предыдущего брата?Вы можете использовать два селектора ax :
!
и?
Там 2 следующие селекторные функции для сиблинга в обычном CSS:
+
является непосредственным последующим селектором сиблинга~
является любым последующим селектором сиблинга. В обычном CSS нет предыдущего селектора sibling.
Однако в ax CSS послепроцессорной библиотеки есть 2 предыдущие селекторные функции:
?
- это предыдущий селектор немедленного (напротив+
)!
является любым предыдущим селектором (см.~
)Рабочий пример:
В следующем примере:
.any-subsequent:hover ~ div
выбирает любой последующийdiv
.immediate-subsequent:hover + div
выбирает немедленный последующийdiv
.any-previous:hover ! div
выбирает любой предыдущийdiv
.immediate-previous:hover ? div
выбирает непосредственный предыдущийdiv
div { display: inline-block; width: 60px; height: 100px; color: rgb(255, 255, 255); background-color: rgb(255, 0, 0); text-align: center; vertical-align: top; cursor: pointer; opacity: 0; transition: opacity 0.6s ease-out; } code { display: block; margin: 4px; font-size: 24px; line-height: 24px; background-color: rgba(0, 0, 0, 0.5); } div:nth-of-type(-n+4) { background-color: rgb(0, 0, 255); } div:nth-of-type(n+3):nth-of-type(-n+6) { opacity: 1; } .any-subsequent:hover ~ div, .immediate-subsequent:hover + div, .any-previous:hover ! div, .immediate-previous:hover ? div { opacity: 1; }
<h2>Hover over any of the blocks below</h2> <div></div> <div></div> <div class="immediate-previous">Hover for <code>?</code> selector</div> <div class="any-previous">Hover for <code>!</code> selector</div> <div class="any-subsequent">Hover for <code>~</code> selector</div> <div class="immediate-subsequent">Hover for <code>+</code> selector</div> <div></div> <div></div> <script src="https://rouninmedia.github.io/axe/axe.js"></script>
По моему пониманию, присваивание s = "Hello"; должен только присваивать значение «Hello» для s, но операция не должна возвращать какое-либо значение.
blockquote>Ваше понимание на 100% неверно. Можете ли вы объяснить, почему вы верите в эту ложную вещь?
Какова аргументация, позволяющая присваивать операторам присваивания значение?
blockquote>Во-первых, назначение не дают значения. Выражение присваивания создает значение. Выражение присваивания является юридическим заявлением; существует только несколько выражений, которые являются юридическими утверждениями в C #: примеры построения экземпляра, приращения, декремента, вызова и присваивания могут использоваться там, где ожидается утверждение.
В C # существует только один вид выражения который не производит какую-то ценность, а именно, обращение к тому, что набирается как возвращающее пустоту. Каждое другое выражение выражает значение или переменную или ссылку или доступ к свойствам или доступ к событиям и т. Д.
Обратите внимание, что все выражения, которые являются законными как утверждения, являются полезными для их побочных эффектов . Это ключевое понимание здесь, и я думаю, возможно, причиной вашей интуиции, что назначения должны быть утверждениями, а не выражениями. В идеале у нас будет ровно один побочный эффект для каждого утверждения и никаких побочных эффектов в выражении. Он является немного странным, что побочный код может использоваться в контексте выражения вообще.
Обоснование возможности этой функции состоит в том, что (1) это часто удобно и (2) является идиоматическим в языках типа C.
Можно заметить, что вопрос был умолял: почему этот идиоматический язык на языках C-типа?
Вы должны были бы спросить Денниса Ритчи, но я предполагаю, что задание почти всегда оставляет значение, которое было просто присвоенный в регистре. C - это очень «близкий к машине» вид языка. Это кажется правдоподобным и в соответствии с дизайном C, что есть языковая функция, которая в основном означает «продолжайте использовать значение, которое я только что назначил». Очень легко написать генератор кода для этой функции; вы просто продолжаете использовать регистр, который сохранил значение, которое было назначено.
Еще один отличный пример использования, я все время использую это:
var x = _myVariable ?? (_myVariable = GetVariable());
//for example: when used inside a loop, "GetVariable" will be called only once
Дополнительное преимущество, которое я не вижу в ответах здесь, заключается в том, что синтаксис для назначения основан на арифметике.
Теперь x = y = b = c = 2 + 3
означает что-то другое в арифметике, чем язык C-стиля ; в арифметике его утверждение, state , что x равно y и т. д., а в языке C-стиля это инструкция, которая делает x равным y и т. д. после нее .
Это говорит о том, что между арифметикой и кодом все еще существует достаточная связь, которая не имеет смысла отрицать, что естественно в арифметике, если нет веской причины. (Другое дело, что языки C-стиля, взятые из использования символа равенства, - это использование == для сравнения равенства. Здесь, хотя, поскольку right-most == возвращает значение, такая цепочка будет невозможна.)
a = b = c
означает, что a
и b
и c
- одно и то же. Изучая язык C-стиля, мы узнаем, что после a = b = c
, a
и b
- это то же, что и c
. Разумеется, разница в семантике, как и сам мой ответ, но все же, когда в детстве я сначала научился программировать на языке, который использовал =
для назначения, но не позволял a = b = c
казаться мне неразумным, хотя ...
– Jon Hanna
23 July 2015 в 22:01
=
для сравнения равенства, поэтому в этом случае a = b = c
должно означать, что a = b == c
означает в языках C-стиля. Я нашел, что цепочка, разрешенная на C, намного интуитивна, потому что я мог бы провести аналогию с арифметикой.
– Jon Hanna
23 July 2015 в 22:04
Помимо упомянутых причин (назначение цепочки, set-and-test внутри цикла while и т. д.), правильно используйте инструкцию using
, в которой эта функция нужна:
using (Font font3 = new Font("Arial", 10.0f))
{
// Use font3.
}
MSDN препятствует объявлению одноразового объекта вне оператора using, так как он будет оставаться в области видимости даже после его размещения (см. статью I статьи MSDN).
Во-первых, он позволяет вам цепочки ваших назначений, как в вашем примере:
a = b = c = 16;
. Для другого он позволяет назначать и проверять результат в одном выражении:
while ((s = foo.getSomeString()) != null) { /* ... */ }
Оба варианта, вероятно, сомнительны, но есть определенные люди, которым нравятся эти конструкции.
return (HttpContext.Current.Items["x"] = myvar);
– Serge Shultz
12 March 2013 в 11:48
Мое любимое использование выражений присваивания для лениво инициализированных свойств.
private string _name;
public string Name
{
get { return _name ?? (_name = ExpensiveNameGeneratorMethod()); }
}
Если присваивание не вернуло значения, строка a = b = c = 16
тоже не работала.
Также возможно иногда использовать такие вещи, как while ((s = readLine()) != null)
.
Таким образом, причина того, что присвоение присваивания возвращает назначенное значение, заключается в том, чтобы позволить вам делать это.
=
, возникающих в выражении, которое не заключено в скобки (не считая parens самого оператора if / while). gcc дает такие предупреждения и тем самым существенно устраняет этот класс ошибок из программ C / C ++, которые скомпилированы с ним. Жаль, что другие авторы компиляторов так мало внимания уделяли этому и нескольким другим хорошим идеям в gcc.
– Jim Balter
23 July 2015 в 21:10
Тот факт, что 'a ++' или 'printf ("foo")' может быть полезен либо как автономный оператор, либо как часть большего выражения, означает, что C должен допускать возможность того, что результаты выражения могут или не могут быть использованы. Учитывая это, существует общее представление о том, что выражения, которые могли бы «вернуть» значение, могут также сделать это. Цепочка присваивания может быть немного «интересной» на C и еще более интересной на C ++, если все рассматриваемые переменные не имеют точно такого же типа. Вероятно, такие способы лучше избегать.
Я думаю, что основной причиной является (намеренное) сходство с C ++ и C. Приведение оператора assigment (и многих других языковых конструкций) ведет себя так, как их аналоги C ++ просто следуют принципу наименьшего удивления, и любой программист, исходящий из другой кудрявый язык может использовать их, не задумываясь. Было легко выбрать для программистов на С ++ одну из основных целей дизайна для C #.
Разве вы не дали ответ?
Обычный случай, когда используется это свойство оператора присваивания, - это чтение строк из файла ...
string line;
while ((line = streamReader.ReadLine()) != null)
// ...
return _myBackingField ?? (_myBackingField = CalculateBackingField());
намного меньше, чем проверка на нуль и присвоение.
– Thomas G. Mayfield
27 September 2010 в 23:02
=
/==
, которая легко устраняется путем отказа от использования значения=
, если она не заключена в скобки. например,if ((x = y))
илиif ((x = y) == true)
, ноif (x = y)
- нет. – Jim Balter 23 July 2015 в 21:01