在字段具有值之前拒绝使用方法

时间:2015-12-21 18:15:07

标签: c#

我打赌这是一个非常基本的设计问题,但由于我很难说出来,我找不到任何在线资源来帮我回答。我使用C#6虽然这是一个设计问题,但我也接受使用c#6独特功能的任何答案。

我的问题:说你有一个简单的课程MyClass,其属性为MyPropMyClass也有方法:

public void InitializeMyProp(someValue)
{
   MyProp = //use the value of someValue to calculate MyProp
}

此外,MyClass有许多使用MyProp的公共方法,例如:

public int DependedMethod1()
{
   //use the value of MyProp to do some calculations. this method might also fail to initialize MyProp and I'm not sure how to handle this situation
   return valueThatDependOnMyProp1;
}

MyProp实例化时,MyClass的值未知。但是,方法DependedMethod1, DependedMethod2, ... , DependedMethodN都取决于MyProp的价值。

我的问题:如何在使用之前确保MyProp已初始化?

我有一些想法,所有这些都是我不喜欢的:

1.当然,我可以为每个方法添加相同的代码DependedMethod

if(MyProp == null) throw exception()

但这有三个缺点:a。重复的代码?湾每次调用方法时,异常都需要处理。

  1. 与我的第一个(坏)想法相吻合,或许可以防止事先调用方法?比如说,将所有DependedMethods放在内部(静态?)类InnerDependedClass中,为MyClass分配InnerDependedClass类型的字段(让它命名为MyField)和在InitializeMyProp实例化。
  2. 这是一个合理的解决方案,因为如果InitializeMyProp失败,我就不会实例化MyField。但问题很严重 - 如果其他类想要使用MyField的方法,它必须先检查它是否为空 - 这有点像询问MyProp是否为空。

    我仍然在努力在这里完全解释自己。

    我的具体问题是:给定二进制文件路径,打开文件,读取其中的前2个字节(偏移键的种类),并保存此键。将文件保存在内存中(我使用InMemoryFileStream)因为源可能会被删除或更改。稍后,当被问到时,使用密钥(再次,偏移)从fileStream中提取特定信息。 问题是,如果文件已损坏/无法打开以进行读取(出于任何原因),则该键将为null。

    我相信我这里有一个很大的设计问题。我的代码是下面的

    public class MyReaderStream : IDisposable, IMyReaderStream
    {
        public MemoryStream InMemoryStream { get; }
    
        public MyReaderStream(string path)
        {
            InMemoryStream = GetInputFile(path);
            //if (InMemoryStream == null) throw new MyReaderException($"path {path} could not be found");
            if (InMemoryStream == null) InMemoryStream = new MemoryStream();
        }
    
        public MyReaderStream(MemoryStream stream)
        {
            InMemoryStream = stream;
            if (InMemoryStream == null) InMemoryStream = new MemoryStream();
        }
    
        public void Dispose()
        {
            InMemoryStream?.Dispose();
        }
    
        public bool VerifyPath(string path)
        {
            var extension = Path.GetExtension(path);
            if (extension != null && !extension.Equals(@".bin")) return false;
            return File.Exists(path);
        }
    
        public MemoryStream GetInputFile(string path)
        {
            if (!VerifyPath(path)) return null;
    
            MemoryStream inMemoryCopy = new MemoryStream();
    
            using (FileStream fs = File.OpenRead(path))
            {
                fs.CopyTo(inMemoryCopy);
            }
    
            return inMemoryCopy;
        }
    }
    public class MyReader
    {
        private readonly IMyReaderStream _stream;
        private uint? offset = null;
    
        public MyReader(IMyReaderStream stream)
        {
            this._stream = stream ?? new MyReaderStream(new MemoryStream());
        }
    
        public uint? GetKey()
        {
            try
            {
                offset = Helpers.ReadWord(_stream.InMemoryStream, 0);
                //might fail if file is corrupted
    
            }
            catch(Exception) {return null;}
        }
        public uint? FirstDependedMethod(){
           return  Helpers.ReadWord(_stream.InMemoryStream, offset + SOME_CONSTANT1); //if offset is null...?
            }
         //more methods like FirstDependedMethod
         //.....
         //.....
      }
    

    更新

    这是一个WPF MVVM项目。模型看起来像这样:

    [NotifyPropertyChanged]
     public class Model
     {
        private NvmReader _reader;
    
        public Model()
        {
            Reader = new NvmReader(null);
        }
    
        public NvmReader Reader
        {
            set { _reader = value; }
            get { return _reader; }
        }
    }
    

    并由ViewModel初始化,如下所示:

    this._model = new Model();    
    

    当用户选择二进制文件的路径时,NvmReader对象才能获得所需的偏移量

1 个答案:

答案 0 :(得分:1)

您应该将班级分为两类。

假设您从课程开始

public class MyClass
{
    public void Initialize(int value)
    {

    }

    public void MethodA() { }
    public void MethodB() { }
}

MethodAMethodB都要求首先调用Initialize方法。

您可以将此类重构为2个单独的类。一个将负责实现MethodAMethodB,另一个负责初始化。这样,类型系统将确保所有内容都已初始化。

public class MyClassFactory
{
    public MyClass Create(int value)
    {
        return new MyClass(value);
    }
}

public class MyClass
{
    internal MyClass(int value)
    {

    }

    public void MethodA() { }
    public void MethodB() { }
}