Поиск

Запрос о реализации интерфейса с помощью is

В примере InterfaceApp вы видели код, использованный для приведения объекта (MyControl) к одному из реализованных в нем интерфейсов (IValidate) и затем для вызова одного из членов этого интерфейса (Validate):

MyControl myControl = new MyControlO;
IValidate val = (IValidate)myControl;
bool success = val.ValidateO;

Что будет, если клиент попытается использовать класс так, как если бы в последнем был реализован метод, на самом деле в нем не реализованный? Следующий пример будет скомпилирован, поскольку интерфейс ISerializable является допустимым. И все же в период выполнения будет передано исключение System.InvalidCastException, так как в MyGrid не реализован интерфейс ISerializable. После этого выполнение приложения прервется, если только исключение не будет явно уловлено.


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 и сравним их.