#c#
Вопрос:
Я пытаюсь сопоставить ссылки на поля в своей структуре, но я не уверен, как я это делаю в качестве настройки случая, а не в случае, если заявления.
Это общая идея, которую я сделал с утверждениями if:
public struct Test
{
// MyObject is a class
public MyObject A;
public MyObject B;
public MyObject C;
public bool Distance(MyObject obj, out float distance){
distance = float.PositiveInfinity;
if(A == obj){
distance = DistanceFrom(A);
return true;
}
if(B == obj){
distance = DistanceFrom(B);
return true;
}
if(C == obj){
distance = DistanceFrom(C);
return true;
}
//object does not relate to this struct so return false
return false;
}
}
В моей фактической структуре более 3 (всего 24), но мне интересно, как я мог бы провести это сравнение с помощью оператора case вместо этого, поскольку это было бы намного чище, чем множество операторов if. Кроме того, я не хочу использовать список из моих 24 ссылок и, следовательно, простой цикл for для его прохождения, так как в конечном итоге мои структуры будут распределены в кучу.
Можно ли выполнить переключение, сравнивая ссылки? Я знаю, как сравнивать по типу объекта, но не в том случае, если они ссылаются на один и тот же объект. Или заявления «если» — это мой единственный вариант здесь?
Комментарии:
1. Здесь это похоже на проблему дизайна. Это ваш настоящий код?
2. Похоже, вы могли бы сделать сингл
if
, как вif(A == obj || B == obj || C == obj)
.3. Это не мой реальный код, так как мой реальный код составляет около 300 строк, и без контекста еще сложнее расшифровать то, что я собираюсь сделать, он делает кучу вещей, поэтому я привел упрощенный пример. Но одна вещь, которая у меня есть, — это множество операторов if, проверяющих, является ли объект одним из объектов, принадлежащих структурам. Что я думал, что изложение дела облегчит написание и также будет более оптимизировано.
4. Решение с использованием коллекций, вероятно, лучше.
5. Вся логика «кучи стека» и «нежелания использовать коллекцию» , возможно, ошибочна.
Ответ №1:
Хотя я согласен с комментаторами в том, что у вас могут возникнуть проблемы с дизайном, вы можете использовать when
фильтр с switch
.
public bool Distance(object obj, out float distance)
{
switch (obj)
{
case var _ when ReferenceEquals(obj, A):
distance = DistanceFrom(A);
return true;
case var _ when ReferenceEquals(obj, B):
distance = DistanceFrom(B);
return true;
case var _ when ReferenceEquals(obj, C):
distance = DistanceFrom(C);
return true;
default:
distance = float.PositiveInfinity;
return false;
}
}
Я знаю, что это выглядит немного странно, но var _
это отбрасывание и говорит, что вас не волнует значение obj
(по крайней мере, само по case
себе, но вы все равно можете использовать obj
в when
.
Вы заявили, что хотите сравнить ссылки. Вот что ReferenceEquals
делает. Если вы этого не хотите, вы можете использовать ==
или то, что вы считаете равным.
Ответ №2:
Я бы посоветовал избегать switch
и просто кодировать такие вещи напрямую.
Попробуйте это:
public bool Distance(object obj, out float distance)
{
MyObject[] variables = new [] { A, B, C };
MyObject match = variables.Where(x => ReferenceEquals(x, obj)).FirstOrDefault();
bool result = match != null;
distance = result ? DistanceFrom(match) : float.PositiveInfinity;
return resu<
}
Или, возможно, немного более гибко:
public float? Distance(object obj)
{
MyObject[] variables = new [] { A, B, C };
MyObject match = variables.Where(x => ReferenceEquals(x, obj)).FirstOrDefault();
return match != null ? (float?)DistanceFrom(match) : null;
}
Комментарии:
1. вы используете
Array
, и операция говорит, что производительность низкая…2. Что означает «низкая производительность»? И как это связано с использованием массива?
3. пожалуйста, ознакомьтесь с комментариями под вопросом.
4. @LeiYang — Но нет никаких доказательств, что это проблема. Также можно переместить массив в поле и, таким образом, достичь того же уровня производительности, что и отдельные поля. Это спорный вопрос.
Ответ №3:
Я думаю, вам нужно прочитать официальные документы, это пример использования случая переключения с when
предложением:
public struct Test
{
// MyObject is a class
public MyObject A;
public MyObject B;
public MyObject C;
public bool Distance(MyObject obj, out float distance){
distance = float.PositiveInfinity;
switch (obj){
case MyObject o when Object.ReferenceEquals(o,A):
distance = DistanceFrom(A);
return true;
case MyObject o when Object.ReferenceEquals(o,B):
distance = DistanceFrom(B);
return true;
case MyObject o when Object.ReferenceEquals(o,C):
distance = DistanceFrom(C);
return true;
default:
return false;
}
}
Комментарии:
1. Как это отвечает на вопрос?
2. Я ошибаюсь в этом примере. Но находится в тех же документах.