public class Interval
{
DateTime LeftBound { get; set; }
DateTime RightBound { get; set; }
public Interval(DateTime left, DateTime right)
{
LeftBound = left;
RightBound = right;
}
}
...
List<Interval> intervals = new List<Interval>
{
new Interval(DateTime.Parse("12:00:00"), DateTime.Parse("13:00:00")),
new Interval(DateTime.Parse("14:00:00"), DateTime.Parse("20:00:00"))
};
...
public Color CheckInterval(DateTime now, List<Interval> timeTable)
{
Color color = Color.Green;
foreach (Interval interval in timeTable)
{
if (now > interval.LeftBound && now < interval.RightBound)
{
color = Color.Red;
break;
}
}
return color;
}
...
label1.ForeColor = CheckInterval(DateTime.Now, intervals);
using System;
using System.Text;
namespace OverrideAndNew
{
class Program
{
static void Main(string[] args)
{
BaseClass bc = new BaseClass();
DerivedClass dc = new DerivedClass();
BaseClass bcdc = new DerivedClass();
// The following two calls do what you would expect. They call
// the methods that are defined in BaseClass.
bc.Method1();
bc.Method2();
// Output:
// Base - Method1
// Base - Method2
// The following two calls do what you would expect. They call
// the methods that are defined in DerivedClass.
dc.Method1();
dc.Method2();
// Output:
// Derived - Method1
// Derived - Method2
// The following two calls produce different results, depending
// on whether override (Method1) or new (Method2) is used.
bcdc.Method1();
bcdc.Method2();
// Output:
// Derived - Method1
// Base - Method2
}
}
class BaseClass
{
public virtual void Method1()
{
Console.WriteLine("Base - Method1");
}
public virtual void Method2()
{
Console.WriteLine("Base - Method2");
}
}
class DerivedClass : BaseClass
{
public override void Method1()
{
Console.WriteLine("Derived - Method1");
}
public new void Method2()
{
Console.WriteLine("Derived - Method2");
}
}
}
\0\u0001\0\0\0ÿÿÿÿ\u0001\0\0\0\0\0\0\0\f\u0002\0\0\0<Test1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null\u0005\u0001\0\0\0\fTest1.Artist\u0003\0\0\0\u001a<FirstName>k__BackingField\u0019<LastName>k__BackingField\u001a<SongTitle>k__BackingField\u0001\u0001\u0001\u0002\0\0\0\u0006\u0003\0\0\0\aMichael\u0006\u0004\0\0\0\aJackson\u0006\u0005\0\0\0\rGive In To Me\v"
[Serializable]
public class Artist
{
private string _firstName;
private string _lastName;
private string _songTitle;
public string FirstName { get => _firstName; set => _firstName = value; }
public string LastName { get => _lastName; set => _lastName = value; }
public string SongTitle { get => _songTitle; set => _songTitle = value; }
}
размер станет меньше (190 байт) и строка поменяется соответственно:\0\u0001\0\0\0ÿÿÿÿ\u0001\0\0\0\0\0\0\0\f\u0002\0\0\0<Test1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null\u0005\u0001\0\0\0\fTest1.Artist\u0003\0\0\0\n_firstName\t_lastName\n_songTitle\u0001\u0001\u0001\u0002\0\0\0\u0006\u0003\0\0\0\aMichael\u0006\u0004\0\0\0\aJackson\u0006\u0005\0\0\0\rGive In To Me\v
\aMichael\aJackson\rGive In To Me
private static string BytesToString(byte[] bytes)
{
char[] chars = Encoding.UTF7.GetString(bytes).ToCharArray();
StringBuilder result = new StringBuilder();
foreach (char c in chars) { result.Append(c); }
return result.ToString();
}
Контракты на интерфейсах
и абстрактных методах
Мощной возможностью контрактов кода является добавление условий к членам интерфейса и абстрактным методам. Двоичное средство перезаписи автоматически привязывает эти условия к конкретным реализациям членов. Специальный механизм позволяет указывать отдельный класс контракта для интерфейсов и абстрактных методов, поэтому можно написать тела методов для хранения условий контрактов. Ниже показано, как это работает:
[ContractClass (typeof (ContractForITest))]
interface ITest
{
int Process (string s);
}
[ContractClassFor (typeof (ITest))]
sealed class ContractForITest : ITest
{
int ITest.Process (string s) // должна использоваться явная реализация.
{
Contract.Requires (s != null);
return 0; // Фиктивное значение, чтобы удовлетворить компилятор.
}
}
Обратите внимание, что для удовлетворения компилятора мы должны вернуть значение при реализации метода ITest.Process. Однако код, возвращающий 0, выполняться не будет. Вместо этого двоичное средство перезаписи извлекает из метода только условия и связывает их с реальными реализациями ITest.Process. Это значит, что экземпляры класса контракта никогда в действительности создаваться не будут (и любые конструкторы, которые вы напишете, также выполняться не будут). Внутри блока контракта можно реализовать присваивание временной переменной, чтобы проще было ссылаться на другие методы интерфейса. Например, если в интерфейсе ITest также определено свойство Message типа string, в ITest.Process можно было бы написать следующий код:
int ITest.Process (string s)
{
ITest test = this;
Contract.Requires (s != test.Message);
...
}
Это проще, чем:
Contract. Requires (s != ((ITest)this).Message);
(Простое использование this Message работать не будет, т.к. свойство Message должно быть реализовано явно.) Процесс определения классов контрактов для абстрактных классов выглядит точно так же за исключением того, что класс контракта должен быть помечен как abstract вместо sealed.