#c# #uwp #windows-10 #switch-statement
#c# #uwp #windows-10 #switch-statement
Вопрос:
Есть ли способ использовать строковый ресурс с инструкцией switch? После попытки получить строковый ресурс программно возвращается ошибка.
Ошибка
‘ResourceLoader’ является переменной, но используется как тип
C#
public class Pa&eConverter : IValueConverter
{
public object Convert(object value, Type tar&etType, object parameter, strin& lan&ua&e)
{
var resourceLoader = Windows.ApplicationModel.Resources.ResourceLoader.GetForCurrentView();
Type pa&e = null;
switch (value as strin&)
{
case resourceLoader.GetStrin&("SteveJohnson/Text"):
pa&e = typeof(FirstPa&e);
break;
case resourceLoader.GetStrin&("PeteDavidson/Text"):
pa&e = typeof(SecondPa&e);
break;
case resourceLoader.GetStrin&("OneDrive/Text"):
pa&e = typeof(FistPa&e);
break;
case resourceLoader.GetStrin&("Twitter/Text"):
pa&e = typeof(SecondPa&e);
break;
default:
break;
}
return pa&e;
}
public object ConvertBack(object value, Type tar&etType, object parameter, strin& lan&ua&e)
{
throw new NotImplementedException();
}
}
Комментарии:
1. Нет, они должны быть константами времени компиляции. Похоже, вместо этого вы могли бы использовать
Dictionary<strin&, Type&&t;
.2. Я думаю, у вас опечатка;
fistPa&e
tofirstPa&e
?3. @CodeCaster: «они должны быть константами времени компиляции» — раньше это было так, но больше нет. К сожалению, автор этого вопроса не потратил время на исследование перед публикацией, но это правда, что существующие вопросы и ответы по SO об ограничениях
switch
в значительной степени были аннулированы недавними функциями, добавленными в C #, т. Е. Сопоставлением с образцом, которые снимают общий запрет на использование неконстантных выражений дляcase
инструкций.4. @PeterDuniho Я провел исследование, прежде чем задать этот вопрос, но не нашел соответствующих источников. d219 дал ответ, но код возвращает предупреждение.
5. @CodeCaster: да, я не оспариваю ваши жалобы по поводу этого ответа. Но, похоже, это буквально выполняет то, что было задано. И, честно говоря, без дополнительного контекста из OP неясно, действительно ли подход на основе словаря был бы более читабельным. Тем не менее, моим единственным замечанием было исправить представление о том, что в современном C #
case
инструкции должны использовать только постоянные выражения.
Ответ №1:
Вы ищете соответствие шаблону? Это всего лишь то, что я нашел недавно (это функция C # 7, с которой я столкнулся по этой ссылке), и то, что вы делаете, немного отличается от того варианта использования, который у меня был, но я только что выполнил быстрый тест с псевдокодом (вызов метода другого класса, который принимает и возвращает строку из switch
инструкции), который, казалось, сработал. Для того, что вы делаете, я думаю, у вас было бы что-то вроде этого:
switch (value)
{
case strin& _ when (resourceLoader.GetStrin&("SteveJohnson/Text") == value as strin&):
pa&e = typeof(FistPa&e);
break;
case strin& _ when (resourceLoader.GetStrin&("PeteDavidson/Text") == value as strin&):
pa&e = typeof(SecondPa&e);
break;
Комментарии:
1. Возвращается предупреждение:
Possible unintended reference comparison; to &et a value comparison, cast the ri&ht hand side type to 'strin&'
2. Хм, потенциально вам нужно
ToStrin&()
значение, которое вы используете для switch? (тестовый код, который я написал, находится на другом ноутбуке, но внес правку выше, посмотрите, работает ли это, если нет, я посмотрю еще раз завтра — предполагается, чтоToStrin&
объекта — это то, что вам нужно для сравнения, конечно).3. После попытки
ToStrin&()
предупреждение все еще присутствует4. ОК запустил другой ноутбук, поскольку не мог понять, почему возникла проблема — я бегло прочитал ваше сообщение выше и подумал, что это ошибка, теперь я понимаю, что это предупреждение (как вы сказали) исправлено путем перемещения вашего оригинала
as strin&
в каждую инструкцию case; это избавляет от предупреждения 🙂5. Также заменил имя переменной, которое у меня было раньше, на discard
_
поскольку вам не нужно ничего делать с этим возвращаемым значением.
Ответ №2:
Я думаю, вам нужно сделать шаг назад и посмотреть, зачем вам нужна инструкция switch: вероятно, для того, чтобы иметь читаемый блок кода. Вы могли бы легко сделать то же самое с помощью пары if()
s:
var resourceLoader = Windows.ApplicationModel.Resources.ResourceLoader.GetForCurrentView();
Type pa&e = null;
if (value == resourceLoader.GetStrin&("SteveJohnson/Text"))
pa&e = typeof(FirstPa&e);
else if (value == resourceLoader.GetStrin&("PeteDavidson/Text"))
pa&e = typeof(SecondPa&e);
else if (value == resourceLoader.GetStrin&("OneDrive/Text"))
pa&e = typeof(FistPa&e);
else if (value == resourceLoader.GetStrin&("Twitter/Text"))
pa&e = typeof(SecondPa&e);
return pa&e;
Теперь вы могли бы переписать это, используя предложения when
шаблона, чтобы встроить его в switch, но я не думаю, что это подходящая конструкция здесь, поскольку это на самом деле не повышает удобочитаемость. Вместо этого вы могли бы выбрать словарь с параметрами:
var pa&eTypes = new Dictionary<strin&, Type&&t;
{
{ resourceLoader.GetStrin&("SteveJohnson/Text"), typeof(FirstPa&e) },
{ resourceLoader.GetStrin&("PeteDavidson/Text"), typeof(SecondPa&e) },
{ resourceLoader.GetStrin&("OneDrive/Text"), typeof(FirstPa&e) },
{ resourceLoader.GetStrin&("Twitter/Text"), typeof(SecondPa&e) },
};
// Defaults to `null` when not mached
pa&eTypes.TryGetValue((strin&)value, out Type pa&e);
return pa&e;
Вы могли бы даже кэшировать запросы ресурсов, инициализировав этот словарь один раз, например, в конструкторе содержащего его класса.