Значения полей
readonly можно менять динамически, в конструкторе класса. Последующие изменения невозможны.
public class MyClass
{
public readonly int Value = 0;
public MyClass()
{
this.Value = 123;
}
}
Для чего это использовать - зависит от фантазии.
Например, можно создать класс
User и сделать
readonly поле, содержащее идентификатор пользователя. Таким образом, идентификатор пользователя можно будет указать только при инициализации класса и, в последующем, изменить его будет невозможно. Это позволит избежать проблем в логике, которые еще предстоит придумать :-)
Если сравнивать со свойствами и константами, то значения
readonly свойств могут меняться в процессе жизненного цикла класса. Значения
readonly полей, как уже было сказано ранее, можно указывать только при объявлении и в конструкторе класса.
Значения констант являются фиксированными и изменять их программно невозможно. Количество типов для констант ограничено, в то время как поля могут иметь любой тип. Константы являются статическими, а поля не обязаны быть таковыми. В этом плане,
readonly поля более гибкие, чем константы.
В дополнение, немного кода (
Console Application):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Timers;
using System.Threading;
namespace ConsoleApplication20
{
class Program
{
static void Main(string[] args)
{
// создаем экземпляр класса
var t = new Toster(199065);
// выводим значение константы ProjectName
// доступ только через Toster
Console.WriteLine(Toster.ProjectName);
// доступа к локальным константам здесь нет
// Toster.CounterPattern
// t.CounterPattern
// выводим заголовок вопроса
Console.WriteLine(t.Title);
// бесконечность - не предел!
while (true)
{
// t.Id = 123;
// мы не можем поменять идентификатор
// следовательно, этот код, логически, будет работать правильно
// выводим число ответов
Console.WriteLine("Ответов: {0}", t.AnswersCount);
// t.AnswersCount = 123
// мы не можем менять значение readonly свойства,
// но оно может меняться внутри экземпляра класса
// пауза 10 сек.
Thread.Sleep(10000);
}
}
}
public class Toster
{
// публичная константа, доступ через Toster
public const string ProjectName = "Тостер";
// локальная константа, доступна только в рамках этого класса
const string CounterPattern = "<span class=\"section-header__counter\" role=\"answers_counter\">";
// публичные поля только для чтения
// значение может быть установлено в конструкторе
public readonly string Title = "Нет данных";
public readonly int Id = 0;
// свойство только для чтения
// значение может меняться в процессе жизни экземпляра класса
// при помощи локальной переменной
private int _AnswersCount = 0;
public int AnswersCount
{
get
{
return _AnswersCount;
}
}
// это просто таймер
private System.Timers.Timer Timer = null;
// а это конструктор<s>, но не Lego</s>
public Toster(int id)
{
if (id <= 0) { return; }
// получаем вопрос
var web = new WebClient();
web.Encoding = Encoding.UTF8;
var result = web.DownloadString(String.Format("https://toster.ru/q/{0}", id));
// из шаблона url тоже можно сделать константу
// либо в классе можно сделать readonly свойство,
// которое будет на лету формировать итоговый адрес:
// return String.Format("https://toster.ru/q/{0}", this.Id)
// устанавливаем значения для полей
this.Id = id;
this.Title = WebUtility.HtmlDecode
(
result.Substring
(
result.IndexOf("<title>") + "<title>".Length,
result.IndexOf("</title>") - result.IndexOf("<title>") - "<title>".Length
)
);
// выдергиваем число ответов на вопрос
this.ParseAnswersCount(result);
// запускаем периодическую проверку <s>Менделеева</s>
Timer = new System.Timers.Timer(10000);
Timer.Elapsed += Timer_Elapsed;
}
// обработчик истечения интервала времени
private void Timer_Elapsed(object sender, EventArgs e)
{
var web = new WebClient();
web.Encoding = Encoding.UTF8;
var result = web.DownloadString(String.Format("https://toster.ru/q/{0}", this.Id));
this.ParseAnswersCount(result);
}
// выдергиватель количества ответов
private void ParseAnswersCount(string value)
{
int startstart = value.IndexOf("Ответы на вопрос");
int start = value.IndexOf(CounterPattern, startstart) + CounterPattern.Length;
int len = value.IndexOf("</span>", start) - start;
_AnswersCount = Convert.ToInt32(value.Substring(start, len));
}
}
}