Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/308.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#_Validation_Arguments_Abstract - Fatal编程技术网

C# 抽象类的参数验证

C# 抽象类的参数验证,c#,validation,arguments,abstract,C#,Validation,Arguments,Abstract,我有以下抽象类: public abstract class FileClient { public abstract File GetFile(string Path); public abstract Task<File> GetFileAsync(string Path); public abstract void MoveFile(string Source, string Destination); } 对所有派生类执行上述参数验证的最佳方法

我有以下抽象类:

public abstract class FileClient {
     public abstract File GetFile(string Path);
     public abstract Task<File> GetFileAsync(string Path);
     public abstract void MoveFile(string Source, string Destination);
}
对所有派生类执行上述参数验证的最佳方法是什么?我个人可以想到以下方法,请随意提及其他方法

1.在每个派生类中执行验证 我个人不喜欢这个解决方案,因为代码重复

2.实施验证方法 在实用程序类或抽象类本身中实现验证方法,并在每个派生类中调用这些验证方法。我不喜欢这一点,因为我想验证的每个现有方法都需要一个新方法。此外,这并不能解决代码重复问题,因为我仍然需要多次调用这些方法

3.模板法设计模式 通过在抽象类的方法中添加验证来实现该模式,并定义派生方法将覆盖的新抽象方法

public File GetFile(string Path) {
    ...Validation
    return DoGetFile(Path);
}
protected abstract File DoGetFile(string Path);
这是我找到的最好的方法,但我不喜欢有重复的方法名(除了Do后缀)和描述

4.使抽象方法虚拟化 使方法虚拟化,并在抽象类中实现验证逻辑。派生类需要首先调用基方法,然后执行它们自己的逻辑

public abstract class FileClient {
     public virtual File GetFile(string Path) {
          ...Validation
          return null;
     }
}

public class FtpClient : FileClient {
     public override File GetFile(string Path) {
          File file = base.GetFile(Path);
          if (file != null) {
              return file;
          }
          ...Logic
     }
}
这种方法非常干净,但我不喜欢它,原因如下:

  • 方法声明为虚拟,仅用于验证。没有逻辑,因为它们总是返回null
  • 派生类将不知道如何处理基类返回的结果
  • 基类将需要为异步方法返回一个非空的任务对象,而派生类需要“等待”异步方法。从性能角度看,这可能重要,也可能不重要,具体取决于需求

  • 第五种方法是使用

    使用代码契约,您可以使用接口契约来实现,在编译期间(实际上使用编译后过程),整个契约将自动注入到整个接口的所有实现中

    您只需要定义一个
    IFileClient
    接口和一个合同类。这可能是最优雅、最强大的解决方案

    请参阅以下代码示例:

    [ContractClass(typeof(IFileClientContract))]
    public interface IFileClient
    {
         File GetFile(string path);
         Task<File> GetFileAsync(string path);
         void MoveFile(string source, string destination);
    }
    
    [ContractClassFor(typeof(IFileClient))]
    public abstract class IFileClientContract : IFileClient
    {
         public File GetFile(string Path)
         {
              Contract.Requires<ArgumentNullException>(!string.IsNullOrEmpty(path));
    
              throw new NotImplementedException();
         }
    
         public Task<File> GetFileAsync(string path)
         {
              Contract.Requires<ArgumentNullException>(!string.IsNullOrEmpty(path));
    
              throw new NotImplementedException();
         }
    
    
         public void MoveFile(string source, string destination)
         {
              Contract.Requires<ArgumentNullException>(!string.IsNullOrEmpty(source));
              Contract.Requires<ArgumentNullException>(!string.IsNullOrEmpty(destination));
    
              throw new NotImplementedException();
         }
    }
    
    // Any implementation of IFileClient will need to fulfill 
    // its contracts, including derived classes of FileClient!
    public abstract class FileClient : IFileClient
    {
         public abstract File GetFile(string Path);
         public abstract Task<File> GetFileAsync(string Path);
         public abstract void MoveFile(string Source, string Destination);
    }
    
    [合同类别(类型(IFileClient合同))]
    公共接口IFileClient
    {
    文件GetFile(字符串路径);
    任务GetFileAsync(字符串路径);
    void MoveFile(字符串源、字符串目标);
    }
    [合同类别(类型(IFileClient))]
    公共抽象类IFileClient合同:IFileClient
    {
    公共文件GetFile(字符串路径)
    {
    Contract.Requires(!string.IsNullOrEmpty(path));
    抛出新的NotImplementedException();
    }
    公共任务GetFileAsync(字符串路径)
    {
    Contract.Requires(!string.IsNullOrEmpty(path));
    抛出新的NotImplementedException();
    }
    公共无效移动文件(字符串源、字符串目标)
    {
    Contract.Requires(!string.IsNullOrEmpty(source));
    Contract.Requires(!string.IsNullOrEmpty(destination));
    抛出新的NotImplementedException();
    }
    }
    //IFileClient的任何实现都需要满足以下条件
    //它的契约,包括FileClient的派生类!
    公共抽象类FileClient:IFileClient
    {
    公共抽象文件GetFile(字符串路径);
    公共抽象任务GetFileAsync(字符串路径);
    公共抽象文件(字符串源、字符串目标);
    }
    
    4号滑坡造成的3号滑坡最严重
    [ContractClass(typeof(IFileClientContract))]
    public interface IFileClient
    {
         File GetFile(string path);
         Task<File> GetFileAsync(string path);
         void MoveFile(string source, string destination);
    }
    
    [ContractClassFor(typeof(IFileClient))]
    public abstract class IFileClientContract : IFileClient
    {
         public File GetFile(string Path)
         {
              Contract.Requires<ArgumentNullException>(!string.IsNullOrEmpty(path));
    
              throw new NotImplementedException();
         }
    
         public Task<File> GetFileAsync(string path)
         {
              Contract.Requires<ArgumentNullException>(!string.IsNullOrEmpty(path));
    
              throw new NotImplementedException();
         }
    
    
         public void MoveFile(string source, string destination)
         {
              Contract.Requires<ArgumentNullException>(!string.IsNullOrEmpty(source));
              Contract.Requires<ArgumentNullException>(!string.IsNullOrEmpty(destination));
    
              throw new NotImplementedException();
         }
    }
    
    // Any implementation of IFileClient will need to fulfill 
    // its contracts, including derived classes of FileClient!
    public abstract class FileClient : IFileClient
    {
         public abstract File GetFile(string Path);
         public abstract Task<File> GetFileAsync(string Path);
         public abstract void MoveFile(string Source, string Destination);
    }