#c# #switch-statement #maintainability
#c# #switch-statement #ремонтопригодность
Вопрос:
Я пытаюсь добавить 300 вызовов в свою программу, но отображать их только в том случае, если значение завершения равно.IsChecked = false;
Если вы создавали эту программу. Как бы вы сохранили вызовы? Я использую коммутатор, но наличие 300 обращений является излишним, есть ли лучший способ?
Любые рекомендации по улучшению кода приветствуются. Я несколько новичок в этом.
Random rand = new Random();
// Constructor
public MainPage()
{
InitializeComponent();
AnswerValue.Visibility = Visibility.Collapsed;
Load();
}
private void Load()
{
int random = rand.Next(1, 4);
switch (random)
{
case 1:
Challenge1();
break;
case 2:
Challenge2();
break;
case 3:
Challenge3();
break;
}
}
private void Challenge1()
{
DifficultyValue.Text = "20%";
CompletionValue.IsChecked = false;
TitleValue.Text = "Chicken or Egg?";
QuestionValue.Text = "Can you answer the ancient question: Which came first the chicken of the egg?";
bmp.UriSource = new Uri("Images/Challenge1.png", UriKind.Relative);
ImageValue.Source = bmp;
ImageValue.Visibility = Visibility.Visible;
ResourceValue.Text = "Resource: Brain Games";
AnswerValue.Text = "The Egg. According to paleontologists, reptiles and dinosaurs existed long before birds and chickens. Fossilized eggs dating back on hundred millions years have been uncovered. Thus it can be said that eggs came before chickens.";
}
private void Challenge2()
{
DifficultyValue.Text = "25%";
CompletionValue.IsChecked = false;
TitleValue.Text = "Halving Seven";
QuestionValue.Text = "Can you prove that seven is half of twelve?";
bmp.UriSource = new Uri("Images/Challenge2.png", UriKind.Relative);
ImageValue.Source = bmp;
ImageValue.Visibility = Visibility.Visible;
ResourceValue.Text = "Resource: Yahoo Questions";
AnswerValue.Text = "Roman numeral for 12 - XII n Cut the roman numeral in half. you will get VII, which is 7.";
}
private void Challenge3()
{
DifficultyValue.Text = "25%";
CompletionValue.IsChecked = false;
TitleValue.Text = "Three-coin flip";
QuestionValue.Text = "You ask a friend about probability, and he tells you the following: The odds of three tossed coins turning up all heads or all tails is one in two, that is, fifty-fifty. That’s because anytime you toss three coins, at least two must match, either two heads or two tails. So that means the third coin—which is equally likely to be heads or tails—determines the odds.” Is your friend right? If not, what are the odds of three tossed coins turning up all heads or all tails?";
bmp.UriSource = new Uri("Images/Challenge3.png", UriKind.Relative);
ImageValue.Source = bmp;
ImageValue.Visibility = Visibility.Visible;
ResourceValue.Text = "Resource: Brain Games";
AnswerValue.Text = "Answer will be available soon";
}
Ответ №1:
Ваши проблемы выглядят ужасно похожими друг на друга, не так ли? Это случай, когда вы хотите извлечь общую структуру данных и представить каждую задачу в виде фрагмента данных.
При единообразном представлении ваших задач вы настраиваете пользовательский интерфейс на основе данных задачи для определенного идентификатора задачи.
Всегда можно переместить ваши данные в файлы XML, файлы JSON или в базу данных, но сначала посмотрите, работает ли для вас простое решение на C #:
// Note: This example is simplified for readability
// Here is the common data structure that can represent all challenges
private class Challenge
{
public string Title { get; set; }
public string Question { get; set; }
public string ImagePath { get; set; }
}
// All of the challenges are defined right here, as simple data
private Challenge[] _allChallenges = new Challenge[]
{
new Challenge
{
Title = "Chicken or Egg?",
Question = "Can you answer the ancient question: Which came first the chicken of the egg?",
ImagePath = "Images/Challenge1.png",
},
new Challenge
{
Title = "Halving Seven?",
Question = "Can you prove that seven is half of twelve?",
ImagePath = "Images/Challenge1.png",
},
}
// Choosing challenges is as simple as indexing into the array
private void Load()
{
int random = rand.Next(1, 4);
Challenge chosenChallenge = _allChallenges[random];
LoadChallenge(chosenChallenge);
}
// Setting up the UI for a challenge means extracting information from the data structure
private void LoadChallenge(Challenge chosenChallenge)
{
TitleValue.Text = chosenChallenge.Title;
QuestionValue.Text = chosenChallenge.Text;
bmp.UriSource = new Uri(chosenChallenge.ImagePath, UriKind.Relative);
ImageValue.Source = bmp;
ImageValue.Visibility = Visibility.Visible;
}
Вы можете рассматривать это как форму декларативного программирования. Важная часть вашей программы, сами вызовы, были преобразованы из императивных инструкций (настройка свойств пользовательского интерфейса) в очень простые объявления данных.
Выполнив это преобразование, вы даже можете проверять каждую задачу, чтобы убедиться, что все части заполнены. Тогда вы будете уверены, что заголовок, вопрос, ресурс, ответ и т.д. установлены для каждого из ваших 300 вызовов.
Ответ №2:
Вы можете сохранить вызовы в базе данных или в файле. Я вижу, что вы используете случайное число и отображаете только 1 вызов. БД может быть чем-то вроде
ChallengeId, DifficultyValue, TitleValue ...
Идентификатором вызова будет номер QuestionID. Таким образом, в зависимости от сгенерированного случайного числа вы можете выбрать конкретный ChallengeId и соответствующие данные.
Комментарии:
1. 1 должен согласиться здесь. Кодирование 300 проблем кажется такой плохой идеей.
Ответ №3:
На что вам действительно следует обратить внимание, так это на инкапсуляцию и полиморфный код. Инкапсулируя ваши свойства like в один класс, у вас есть лучший способ представления «Задачи» в целом, а возможность повторного использования частей, которые вам приходится вводить снова и снова ( .Text = "..."
), сделает вашу будущую жизнь кодирования бесконечно лучше. Конечно, даже кодирование списка Challenge
объектов, как у меня ниже, было бы неинтересным, вам нужно когда-нибудь ввести эти данные где-нибудь. Мы просто будем рассматривать это как упражнение по программированию, вы можете легко адаптировать приведенный ниже код для заполнения _challenges
из базы данных или сериализованного файла.
public class Challenge
{
public int Id {get;set;}
public int Difficulty {get;set;}
public bool IsCompleted {get;set;}
public string Title {get;set;}
public string Question {get;set;}
public string Answer {get;set;}
}
public class MainPage
{
private List<Challenge> _challenges;
private Random rand = new Random();
public MainPage()
{
_challenges = new List<Challenge> {
new Challenge {
Id = 1,
Difficulty = 20,
Title = "What came first?",
Question = "The chicken or the egg?",
Answer = "The egg." },
new Challenge {
Id = 2,
Difficulty = 30,
Title = "Make 7 from 12?",
Question = "Can you prove 7 is half of 12?",
Answer = "VII" }};
}
public void LoadChallenge(Challenge challenge)
{
Difficulty.Test = String.Format("%{0}", callenge.Difficulty);
Completeted.Value = challenge.IsCompleted;
Title.Test = challenge.Title;
// etc
}
public void StartNewChallenge()
{
Challenge nextChallenge = null;
while(nextChallenge == null)
{
var nextId = rand.Next(1,2);
nextChallenge = _challenges
.Where(x => x.Id == nextId amp;amp; !x.IsCompleted)
.SingleOrDefault(); // default to null if completed == true
}
LoadChallenge(nextChallenge);
}
}
Ответ №4:
Еще одной альтернативой может быть какой-то фабричный метод:
MyForm.cs
public class MyForm
{
Random rand = new Random();
// Constructor
public MainPage()
{
InitializeComponent();
AnswerValue.Visibility = Visibility.Collapsed;
Load();
}
private void Load()
{
int random = rand.Next(1, 4);
DisplayChallenge(ChallengeFactory.GetChallenge(random));
}
private void DisplayChallenge(ChallengeFactory.Challenge challengeToDisplay)
{
DifficultyValue.Text = String.Format("{0}%", challengeToDisplay.Difficulty);
CompletionValue.IsChecked = challengeToDisplay.IsChecked;
TitleValue.Text = challengeToDisplay.Title;
QuestionValue.Text = challengeToDisplay.Question;
ImageValue.Source = challengeToDisplay.ImageSource;
ImageValue.Visibility = challengeToDisplay.Visible;
ResourceValue.Text = challengeToDisplay.ResourceValue;
AnswerValue.Text = challengeToDisplay.Answer;
}
}
ChallengeFactory.cs
public static class ChallengeFactory
{
public class Challenge
{
public int Difficulty { get; set; }
public bool IsChecked { get; set; }
public string Title { get; set; }
public string Question { get; set; }
public Uri ImageSource { get; set; }
public bool Visible { get; set; }
public string ResourceValue { get; set; }
public string Answer { get; set; }
private Challenge(int difficulty, bool isChecked, string title, string question, Uri imageSource, bool visible, string resourceValue, string answer)
{
// assign each of the arguments to the instance properties
}
}
public static Challenge GetChallenge(int challengeNumber)
{
switch(challengeNumber)
{
case 1:
return new Challenge(20, false, "Chicken or Egg?", "Can you answer the ancient question: Which came first the chicken of the egg?", new Uri("Images/Challenge1.png", UriKind.Relative), true, "Resource: Brain Games", "The Egg...");
break;
case 2:
// new challenge for challenge #2
break;
case 3:
// new challenge for challenge #3
break;
}
}
}
Обратите внимание, что я сделал класс Challenge вложенным классом внутри заводского класса.Хорошая вещь в этом заключается в том, что вы можете создать конструктор вызова private
(это означает, что вы не можете создавать «недопустимые» типы вызовов с помощью чего-либо, кроме фабричного метода. Плохая вещь в этом заключается в том, что вам нужно дополнительно квалифицировать класс вызова, добавив к нему префикс содержащего его класса, то есть ChallengeFactory
. Я думаю, что в этом случае стоит добавить дополнительный квалификатор.
В конечном счете, я думаю, вы застряли в необходимости где-то создавать коммутатор, если планируете определять все свои проблемы в коде. Как говорили другие, вы можете значительно сократить объем кода, который вам нужно написать (и, следовательно, коммутатор), определив свои задачи во внешнем источнике данных (например, базе данных) и имея единый метод для чтения, анализа и создания Challenge
экземпляра.