Advertisement
Ne-Biolog

Untitled

Mar 3rd, 2018
66
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 21.96 KB | None | 0 0
  1. Добрый день.
  2.  
  3. Так как при сдаче работ часто возникают одни и те ошибки, высылаю список
  4. типичных недочетов и рекомендаций. Если что-ли из перечисленного вам пока не
  5. понятно, то либо можете изучить это самостоятельно, либо подождать, пока это
  6. вам объяснят на лекции.
  7.  
  8. 1. "Если в лабораторной работе необходимо изменять(!) строку, необходимо
  9. использовать класс StringBuilder" - если строку не изменяете, StringBuilder
  10. использовать не надо! Не надо "добавлю на всякий случай StringBuilder, а то
  11. вдруг не примет"!
  12.  
  13. string s = "lorem ipsum";
  14. // просто берем символ из строки, строка при этом никак не изменится,
  15. // нет необходимости использовать StringBuilder
  16. char ch = s[5];
  17.  
  18. // заменить символ у строки не получится, т.к. строки неизменяемы
  19. string a = "duck";
  20. a[0] = 'l';
  21. // поэтому в данном случае придется использовать StringBuilder
  22. StringBuilder sb = new StringBuilder("duck");
  23. sb[0] = 'l';
  24. Console.WriteLine(sb);
  25.  
  26. // Следующие действия "изменяют" строку: исходная строка-объект
  27. // не изменяется, но в результате операции создается новый объект,
  28. // в котором будут отражены соответствующие изменения,
  29. // и этот объект будет присвоен в переменную
  30.  
  31. // методы Insert, Remove, Replace, Concat класса string
  32.  
  33. // соединение (конкатенция) строк
  34. string a = "speech";
  35. string b = "less";
  36. a = a + b;
  37. // следует использовать StringBuilder.Append
  38. sb = new StringBuilder("speech");
  39. sb.Append("less");
  40. Console.WriteLine(sb);
  41.  
  42. // если же надо присоединять в начало
  43. string c = "on";
  44. c = b + c;
  45. // можно использовать StringBuilder.Insert
  46. sb = new StringBuilder("on");
  47. sb.Insert(0, "less");
  48. Console.WriteLine(sb);
  49.  
  50.  
  51. // если к строке применяется небольшое количество изменяющих операций -
  52. // то можно обойтись без StringBuilder:
  53.  
  54. // допустимо
  55. string e = "Следующая лекция будет в пятницу 9 марта";
  56. e = e.Replace("пятницу", "субботу").Replace("9", "3");
  57. Console.WriteLine(e);
  58.  
  59. // чем больше изменяющих операций применяете к строке - тем вероятней
  60. // ее следует заменить на StringBuilder. Если делаете какие-либо
  61. // изменения в цикле, однозначно следует использовать StringBuilder:
  62.  
  63. // данный код необходимо переписать с использованием StringBuilder!!!
  64. Random random = new Random();
  65. string randomString = "";
  66. for (int i = 0; i < 30; ++i) {
  67. randomString += (char)('a' + random.Next(26));
  68. }
  69. Console.WriteLine(randomString);
  70.  
  71. 2. Random.Next включает нижнюю границу и не включает верхнюю. Например,
  72. Random.Next(5, 9) может генерировать значения 5, 6, 7, 8, а
  73. Random.Next(4) может генерировать значения 0, 1, 2, 3.
  74.  
  75. (Одна из причин, почему верхняя граница не включается, следующая:
  76. в массиве длины length мы можем обращаться к элементам с индексами
  77. 0, 1, 2, ..., length-2, length-1. Если метод Next не будет включать верхнюю
  78. границу, то для получения случайного элемента из массива мы можем написать:
  79.  
  80. arr[random.Next(arr.length)]
  81.  
  82. Если же метод Next будет включать верхнюю границу, то придется писать:
  83.  
  84. arr[random.Next(arr.length - 1)]
  85.  
  86. Так как многие программисты могут забывать вычесть эту единицу,
  87. было решено верхнюю границу не включать.)
  88.  
  89. 3. Random - генератор псевдослучайных чисел (подробнее о ГПСЧ можете почитать,
  90. например, на википедии): последовательность генерируемых случайных значений
  91. зависит от начального состояния генератора. Два объекта Random с одинаковым
  92. начальным состоянием будут генерировать одинаковые последовательности значений.
  93. Конструктор класса Random, принимающий int, позволяет задавать начальное
  94. состояние генератора. Например:
  95.  
  96. Random first = new Random(1408);
  97. Random second = new Random(1408);
  98.  
  99. Console.WriteLine(first.Next(100)); // 30
  100. Console.WriteLine(first.Next(100)); // 95
  101. Console.WriteLine(first.Next(100)); // 94
  102.  
  103. Console.WriteLine(second.Next(100)); // 30
  104. Console.WriteLine(second.Next(100)); // 95
  105. Console.WriteLine(second.Next(100)); // 94
  106.  
  107.  
  108. Конструктор без параметров класса Random задает начальное состояние генератора
  109. на основе текущего времени. Если создать два объекта Random при помощи
  110. конструкторов без параметров примерно в один и тот же момент времени, у них
  111. будет одно и то же начальное состояние. Например:
  112.  
  113. Random first = new Random();
  114. Random second = new Random();
  115.  
  116. Console.WriteLine(first.Next(100)); // a
  117. Console.WriteLine(first.Next(100)); // b
  118. Console.WriteLine(first.Next(100)); // c
  119.  
  120. // будут выведены те же три числа, которые были выведены выше
  121. Console.WriteLine(second.Next(100)); // a
  122. Console.WriteLine(second.Next(100)); // b
  123. Console.WriteLine(second.Next(100)); // c
  124.  
  125.  
  126. Поэтому необходимо создавать один объект класса Random на всю программу и его
  127. использовать, а не создавать новый объект каждый раз, когда необходимо вызвать
  128. метод Next.
  129.  
  130. 4. В 3 лабораторной работе наличие свойств у класса обязательно. Также крайне
  131. желательна проверка в методе set свойства на то, что вводятся
  132. корректные/допустимые значения. Напомню, свойства выглядят вот так:
  133.  
  134. public class Student
  135. {
  136. private int _age;
  137. private string _name;
  138.  
  139. public int Age
  140. {
  141. get { return _age; }
  142. set { _age = value > 0 ? value : 0; }
  143. }
  144.  
  145. public string Name
  146. {
  147. get { return "My name is " + _name; }
  148. set { _name = value; }
  149. }
  150. }
  151.  
  152. Автосвойства в 3 работе использовать нельзя. Автосвойства выглядят следующим
  153. образом:
  154.  
  155. public class Person
  156. {
  157. public string Name { get; set; }
  158. }
  159.  
  160. 5. Инициализация полей класса должна происходить в конструкторе того же класса,
  161. в котором эти поля объявлены.
  162.  
  163. Например, так делать не рекомендуется:
  164.  
  165. public class Human {
  166. protected int age;
  167. protected string name;
  168.  
  169. public int GetNameLength() {
  170. return name.Length;
  171. }
  172. }
  173.  
  174. public class Student : Human {
  175.  
  176. private string university;
  177. private string speciality;
  178.  
  179. public Student(int age, string name, string university, string speciality) {
  180. this.age = age;
  181. this.name = name;
  182. this.university = university;
  183. this.speciality = speciality;
  184. }
  185. }
  186.  
  187. Поля age и name объявлены в классе Human, а инициализируются в конструкторе
  188. класса Student. Вместо этого мы должны инициализировать их в конструкторе
  189. класса Human, а в конструкторе класса Student вызвать конструктор базового
  190. класса:
  191.  
  192. public class Human {
  193. protected int age;
  194. protected string name;
  195.  
  196. public Human(int age, string name) {
  197. this.age = age;
  198. this.name = name;
  199. }
  200. }
  201.  
  202. public class Student : Human {
  203.  
  204. private string university;
  205. private string speciality;
  206.  
  207. public Student(int age, string name, string university, string speciality) : base(age, name) {
  208. this.university = university;
  209. this.speciality = speciality;
  210. }
  211. }
  212.  
  213.  
  214. Так следует делать как минимум по двум причинам:
  215.  
  216. а) Невозможность или сложность работы непосредственно с самим базовым классом:
  217.  
  218. // все поля проинициализированы
  219. Student student = new Student(18, "Петя", "бгуир", "ИиТП");
  220.  
  221. // поля age и name не инициализированы, дальнейшая работа с объектом может вести к ошибкам
  222. Human human = new Human();
  223.  
  224. // например, при обращении к name.Length внутри метода GetNameLength() произойдет ошибка
  225. Console.WriteLine(human.GetNameLength());
  226.  
  227. б) В случае наследования от класса Human каких-либо других классов (например,
  228. Рабочий, Пенсионер, Школьник и т.д.) при использовании первого подхода можно
  229. забыть проинициализировать поля age и name в конструкторах наследников. При
  230. использовании второго подхода компилятор "напомнит" их проинициализировать,
  231. требуя вызвать конструктор базового класса.
  232.  
  233. 6. В случае перегрузки конструкторов (данный подход можно использовать и в
  234. случае перегрузки методов) желательно одну версию конструктора считать
  235. "базовой", а в остальных версиях вызывать эту "базовую" версию. Это позволит в
  236. случае необходимости какого-либо изменения вносить изменения только в одном
  237. конструкторе, остальные изменятся автоматически.
  238.  
  239. Рассмотрим на примере:
  240.  
  241. public class Student {
  242. private int age;
  243. private string name;
  244. private string university;
  245. private string speciality;
  246.  
  247. public Student(int age, string name, string university, string speciality) {
  248. this.age = age;
  249. this.name = name;
  250. this.university = university;
  251. this.speciality = speciality;
  252. }
  253.  
  254. public Student(int age, string name, string speciality) {
  255. this.age = age;
  256. this.name = name;
  257. this.university = "БГУИР";
  258. this.speciality = speciality;
  259. }
  260.  
  261. public Student(int age, string name) {
  262. this.age = age;
  263. this.name = name;
  264. this.university = "БГУИР";
  265. this.speciality = "ИиТП";
  266. }
  267. }
  268.  
  269. В данном случае первый конструктор является наиболее "универсальным" -
  270. позволяет присвоить значения всем полям класса, второй и третий конструктор
  271. менее "универсальны": второй конструктор задает полю university значение
  272. "БГУИР" и тем самым не позволяет присваивать различные значения этому полю,
  273. для третьего конструктора размышления аналогичны второму. Поэтому желательно
  274. из второго и третьего конструктора вызывать первый:
  275.  
  276. public Student(int age, string name, string speciality) : this(age, name, "БГУИР", speciality) { }
  277. public Student(int age, string name) : this(age, name, "БГУИР", "ИиТП") { }
  278.  
  279.  
  280. Тогда если нам необходимо добавить в конструктор какую-нибудь функциональность
  281. (например, убрать начальные и конечные пробелы в строках, тем самым
  282. преобразовав " бгуир " в "бгуир"), достаточно это сделать в одном
  283. конструкторе, в остальных конструкторах данные изменения применятся
  284. автоматически:
  285.  
  286. public class Student {
  287. // поля age, name, ...
  288.  
  289. public Student(int age, string name, string university, string speciality) {
  290. this.age = age;
  291. this.name = name.Trim();
  292. this.university = university.Trim();
  293. this.speciality = speciality.Trim();
  294. }
  295.  
  296. public Student(int age, string name, string speciality) : this(age, name, "БГУИР", speciality) { }
  297.  
  298. public Student(int age, string name) : this(age, name, "БГУИР", "ИиТП") { }
  299.  
  300. public override string ToString() {
  301. return $"{age} {name} {university} {speciality}";
  302. }
  303. }
  304.  
  305. public class Program
  306. {
  307. public static void Main(string[] args)
  308. {
  309. Student student = new Student(18, " Петя ", " бгуир ", " ВМСиС ");
  310. Console.WriteLine(student); // "18 Петя бгуир ВМСиС"
  311.  
  312. student = new Student(19, " Вася ", " ПОИТ ");
  313. Console.WriteLine(student); // "19 Вася БГУИР ПОИТ"
  314.  
  315. student = new Student(21, " Леня ");
  316. Console.WriteLine(student); // "21 Леня БГУИР ИиТП"
  317. }
  318. }
  319.  
  320. 7. Желательно не складывать строки при помощи оператора +, лучше использовать
  321. форматирование (из-за обилия символов " и + затруднительно понять, как должна
  322. выглядеть результирующая строка).
  323.  
  324. string expr;
  325. int a = 5;
  326. int b = 7;
  327. string name = "Вася";
  328. int age = 18;
  329. string speciality = "ИиТП";
  330.  
  331. // можно, но лучше так не писать
  332. Console.WriteLine("Я - " + name + ", мне " + age + " лет, я студент специальности " + speciality);
  333.  
  334. expr = a + " + " + b + " равно " + (a + b);
  335. Console.WriteLine(expr);
  336.  
  337. // так лучше
  338. Console.WriteLine("Я - {0}, мне {1} лет, я студент специальности {2}", name, age, speciality);
  339.  
  340. expr = string.Format("{0} + {1} равно {2}", a, b, a + b);
  341. Console.WriteLine(expr);
  342.  
  343. // "синтаксический сахар" для string.Format, лаконичней и удобней
  344. // данное действие называется интерполяцией строк
  345. expr = $"{a} + {b} равно {a + b}";
  346. Console.WriteLine(expr);
  347.  
  348. 8. Старайтесь не читать с консоли и не писать в консоль в конструкторах и
  349. методах классов Human, Student и т.д. - работу с консолью следует
  350. осуществлять в методе Main.
  351.  
  352. 9. У многих встречался такой метод:
  353.  
  354. public class Student : Human {
  355.  
  356. // ...
  357.  
  358. public void showInfo() {
  359. Console.WriteLine($"Имя: {name} Возраст: {age} Университет: {university} Специальность: {speciality}");
  360. }
  361. }
  362.  
  363. // где-то в методе main выводим информацию на консоль
  364. student.showInfo();
  365.  
  366. Во-первых: метод возвращает void и при этом внутри себя печатает на консоль,
  367. лучше сделать так, чтобы он возвращал строку, а в методе Main печатаем
  368. возвращаемое значение на консоль.
  369. Во-вторых: цель данного метода - преобразовать наш объект в строковое
  370. представление, для этой цели традиционно используется метод ToString(), поэтому
  371. ваш метод следует так и назвать.
  372. В-третьих: данный метод отображает как свои поля, так и поля базового класса,
  373. лучше в методе отображать поля только текущего класса, для отображения полей
  374. базового класса лучше вызывать соответствующий метод базового класса.
  375.  
  376. С учетом этого данный метод лучше переписать следующим образом:
  377.  
  378. public class Human {
  379.  
  380. // ...
  381.  
  382. public override string ToString() {
  383. return $"Имя: {name} Возраст: {age}";
  384. }
  385. }
  386.  
  387. public class Student : Human {
  388.  
  389. // ...
  390.  
  391. public override string ToString() {
  392. return $"{base.ToString()} Университет: {university} Специальность: {speciality}";
  393. }
  394. }
  395.  
  396. // в методе main выводим на консоль
  397. Student student = new Student(18, "Петя", "бгуир", "ИиТП");
  398. // здесь неявно вызывается Student.ToString()
  399. Console.WriteLine(student);
  400.  
  401. 10. Если возникает желание кусок кода скопировать с места А в место Б -
  402. подумайте, может быть лучше этот кусок кода поместить в метод и в местах А и Б
  403. поместить вызов этого метода.
  404.  
  405. 11. Если название переменной, класса, функции и т.д. состоит из нескольких слов,
  406. первые буквы второго и последующих слов следует делать большими - someLongName,
  407. но не some_long_name (в некоторых других языках принято так писать, но не в c#)
  408. и не somelongname.
  409.  
  410. Названия классов, методов, свойств следует начинать с большой буквы;
  411. названия полей, локальных переменных, параметров методов следует начинать с
  412. маленькой буквы.
  413. (В примерах кода вы можете увидеть, что названия приватных полей начинают с
  414. символа _, например _name. Единого мнения, следует ли так делать, нет, поэтому
  415. данного правила можете не придерживаться.)
  416.  
  417. Чтобы быстро переименовать функцию, переменную, класс и т.д. во всех местах,
  418. достаточно выделить название в одном месте, нажать правой кнопкой мыши,
  419. выбрать в меню "переименовать", ввести новое название и нажать enter. Во всех
  420. остальных местах название изменится автоматически.
  421.  
  422. 12. Читайте методички - в них всего 83 и 161 страницы, это не Рихтер на 1000+
  423. страниц. В них в очень краткой форме собрано очень много полезного материала.
  424.  
  425. В методичке "Базовые технологии платформы .NET" есть таблицы со статическими и
  426. экземплярными методами стандартных типов: Contains, IndexOf, IsUpper и т.д.
  427. Ознакомьтесь с этими таблицами, с тем, что делают эти методы, часто с
  428. использованием этих методов можно написать более короткий код.
  429.  
  430. С уважением,
  431. Гербик А.И.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement