Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 与多接口实现的混淆_C#_Oop_Inheritance_Interface_Refactoring - Fatal编程技术网

C# 与多接口实现的混淆

C# 与多接口实现的混淆,c#,oop,inheritance,interface,refactoring,C#,Oop,Inheritance,Interface,Refactoring,我有以下一组接口和类 public interface IValidatableObject { List<string> ValidationErrors { get; } bool Validate(); } public class ValidatableObject : IValidatableObject { public List<string>ValidationErrors { get; } public bool Validat

我有以下一组接口和类

public interface IValidatableObject
{
   List<string> ValidationErrors { get; }
   bool Validate();
}

public class ValidatableObject : IValidatableObject
{
   public List<string>ValidationErrors { get; }
   public bool Validate()
   {
      //dostuff
   }
}

public interface IDeviceDataObject
{
   int Id { get; set; }
   string Name { get; set; }
}

public class DeviceDataObject : ValidatableObject, IDeviceDataObject
{
   public int Id { get; set; }
   public string Name { get; set; }
}

public class DeviceService
{
   public bool ValidateDevice(IDeviceDataObject device)
   {
       return device.Validate(); // This throws a compiler error
   }
}

您可以将
ValidateDevice
方法设置为泛型,让调用方传入实现正确接口组合的对象实例-这将允许您的接口保持独立,并仍然强制执行类型安全:

public class DeviceService
{
   public bool ValidateDevice<T>(T device) where T: IDeviceDataObject, IValidatableObject
   {
       return device.Validate(); 
   }
}
公共类设备服务
{
公共bool验证设备(T设备),其中T:IDeviceDataObject,IValidatableObject
{
返回设备.Validate();
}
}

我可能理解这里有些错误(我不知道您的类体系结构作为一个整体),但是为什么您的ValidateDevice方法不只接受可验证的对象呢?签名看起来像:

public bool ValidateDevice(IValidatableObject someobj)
这不是表示进行验证的方法的功能的地方吗:它接受可验证的东西。其他一切都可以保持原样(例如,不要让
IDeviceDataObject
继承自
IValidatableObject
,因为您可能想表示,并非每个devicedataobject都是可验证的)

第二种方法是,如果要确保
ValidateDevice
只接受实现
IDeviceDataObject
的对象,还可以尝试交叉转换到
IValidatableObject

public bool ValidateDevice(IDeviceDataObject someobj)
{
    if(someobj is IValidatableObject)
    {
        return ((IValidatableObject)device).Validate();
    }
    return //something that makes sense if the device is not validatable
}

您可以简单地强制转换为表对象

public class DeviceService 
{ 
   public bool ValidateDevice(IDeviceDataObject device) 
   { 
       IValidatableObject v = device as IValidatableObject;

       if (v != null)
           return device.Validate();
       return false;
   } 
} 

我从这些名称中推断了很多,但在我看来,
IDeviceDataObject
IValidatableObject
是两个独立的概念。您可以拥有实现
IDeviceDataObject
IValidatableObject
,或者两者都实现的对象(是吗?)。如果这是真的,那么两个接口之间就没有“是”关系(您不会假设
IDeviceDataObject
IValidatableObject
),因此从另一个接口继承一个接口似乎是错误的


对于
ValidateDevice
方法(或任何方法)--如果要将参数用作
IDeviceDataObject
,则参数应为该类型。如果要将参数用作
IValidatableObject
,则该参数应为该类型。如果它可能同时使用这两种功能,那么您可能希望传入一种不太特定的类型,然后进行运行时检查(使用C#“is”或“as”)以查看对象是否支持特定的接口。

为什么您的ValidateDevice签名不像
public bool ValidateDevice(IValidatableObject someobj)
?这不是验证方法功能的表现吗:它需要一些可验证的东西。其他一切都可以保持原样,这很公平。但是如果它是一个CreateDevice方法,需要知道它是一个传入的IDeviceDataObject,但它仍然需要具有IValidatableObject功能,那该怎么办呢?那么——因为我不知道这里的大图——所有IDeviceDataObject都应该是可验证的吗?如果是,则让
IDeviceDataObject
IValidatableObject
继承。如果不是,那么这不是解决方案。有时候真的很简单:这只是一个什么在语义上有意义的问题。依次将其转换为代码是一个相当简单的步骤。但是所有处于有效状态但未实现
IValidatableObject
的设备都将无法通过验证。@Eranga-和?它们通知有效的唯一方法是实现IValidatableObject。我看不出有什么问题。API在撒谎。我希望
ValidateDevice
方法基于
IDeviceDataObject
契约进行验证。我必须完成
ValidateDevice
的实现,我知道我还必须实现
IValidatableObject
。@Eranga-不,API没有撒谎。如果对象未实现IValidatableObject,则无法验证该对象。就这么简单。为了解决您的问题,有一种叫做“文档”的东西。
public class DeviceService 
{ 
   public bool ValidateDevice(IDeviceDataObject device) 
   { 
       IValidatableObject v = device as IValidatableObject;

       if (v != null)
           return device.Validate();
       return false;
   } 
}