В примере
InterfaceApp
вы видели код, использованный для приведения объекта
(MyControl)
к одному из реализованных в нем интерфейсов
(IValidate)
и затем для вызова одного из членов этого интерфейса
(Validate):
MyControl myControl = new MyControlO;
IValidate val = (IValidate)myControl; bool success = val.ValidateO;
Что будет, если клиент попытается использовать класс так, как если бы в последнем был реализован метод, на самом деле в нем не реализованный? Следующий пример будет скомпилирован, поскольку интерфейс
ISerializable
является допустимым. И все же в период выполнения будет передано исключение
System.InvalidCastException,
так как в
MyGrid
не реализован интерфейс
ISerializable.
После этого выполнение приложения прервется, если только исключение не будет явно уловлено.
using System;
public class FancyControl
{
protected string Data; public string data {
get {
return this.Data; }
set {
this.Data = value;
> } }
interface ISerializable {
bool Save(); }
interface IValidate {
bool ValidateO; }
class MyControl : FancyControl, IValidate {
public MyControlO
{
data = "my grid data";
>
public bool ValidateO {
Console.WriteLine("Validating...{0}", data);
return true; > }
class IsOperatorlApp {
public static void Main()
{
MyControl rayControl = new MyControlO;
ISerializable ser = (ISerializable)myControl;
// Заметьте: в результате этого будет сгенерировано // исключение System.InvalidateCastException, поскольку // в классе не реализован интерфейс ISerializable. bool success = ser.Save();
Console.WriteLine("The saving of '{0}' was {1}successful",
myControl.data,
(true == success ? "" : "not "));
} }
Конечно, улавливание исключения не повлияет на то, что предназначенный для выполнения код в этом случае не будет исполнен. Способ запроса объекта
перед
попыткой его приведения — вот что вам нужно. Один из способов — задействовать оператор
is.
Он позволяет в период выполнения проверять совместимость одного типа с другим. Оператор имеет следующий вид, где
выражение —
ссылочный тип:
выражение
is
тип
Результат оператора
is —
булево значение, которое затем можно использовать с условными операторами. В следующем примере я изменил код, чтобы проверять совместимость между классом
MyControl
и интерфейсом
ISerializable
перед попыткой вызова метода
ISerializable:
using System;
public class FancyControl
{
protected string Data; public string data {
get
{
return this.Data;
}
set
{
this.Data = value;
} }
}
interface ISerializable {
bool Save(); >
interface IValidate {
bool ValidateO;
}
class MyControl : FancyControl, IValidate {
public MyControlO
{
data = "my grid data";
}
public bool ValidateQ {
Console.WriteLine("Validating...{0}", data);
return true; > }
class IsOperator2App {
public static void Main()
{
MyControl myControl = new MyControlO;
if (myControl is ISerializable) {
ISerializable ser = (ISerializable)myControl;
bool success = ser.SaveO;
Console. WriteLinef'The saving of '{0}' was "+ "{1}successful", myControl.data,
(true == success ? "" : "not ")); }
else {
Console.WriteLine("The ISerializable interface "+ "is not implemented."); > } }
Вы увидели, как оператор
is
позволяет проверить совместимость двух типов, чтобы гарантировать их корректное использование. А теперь рассмотрим его близкого родственника — оператор
as
и сравним их.