C#中的多个构造函数

时间:2013-02-11 14:32:07

标签: c# constructor

我有需要数据的类,这可以是字节或文件路径。

此刻我将文件读入字节数组,然后设置类。在另一个分隔符中,它直接从作为参数传递的字节设置类。

我想要第一个构造函数(文件路径)来调用第二个(字节),如:

    public DImage(byte[] filebytes) : this()
    {
        MemoryStream filestream = null;
        BinaryReader binReader = null;
        if (filebytes != null && filebytes.Length > 0)
        {
            using (filestream = new MemoryStream(filebytes))
            {
                if (filestream != null && filestream.Length > 0 && filestream.CanSeek == true)
                {
                    //do stuff
                }
                else
                    throw new Exception(@"Couldn't read file from disk.");
            }
        }
        else
            throw new Exception(@"Couldn't read file from disk.");
    }


    public DImage(string strFileName) : this()
    {
        // make sure the file exists
        if (System.IO.File.Exists(strFileName) == true)
        {
            this.strFileName = strFileName;
            byte[] filebytes = null;
            // load the file as an array of bytes
            filebytes = System.IO.File.ReadAllBytes(this.strFileName);
            //somehow call the other constructor like
            DImage(filebytes);                         
        }
        else
           throw new Exception(@"Couldn't find file '" + strFileName);

    }

那么如何从第二个调用第一个构造函数(以保存复制和粘贴代码)?

3 个答案:

答案 0 :(得分:4)

您可以创建一个以byte[]为参数的私有方法,比如ProcessImage(byte[] myparam),两个构造函数都会调用它来处理您的字节。

附注:您可能需要考虑使用stream代替byte[]


快速举例:

public DImage(byte[] filebytes) : this()    // Remove if no parameterless constructor
{
    MemoryStream filestream = null;
    BinaryReader binReader = null;
    if (filebytes != null && filebytes.Length > 0)
    {
        using (filestream = new MemoryStream(filebytes))
        {
            this.ProcessStream(filestream);
        }
    }
    else
        throw new Exception(@"Couldn't read file from disk.");
}

public DImage(Stream stream) : this()   // Remove if no parameterless constructor
{
    this.ProcessStream(stream);
}    

public DImage(string strFileName) : this()  // Remove if no parameterless constructor
{
    // make sure the file exists
    if (System.IO.File.Exists(strFileName) == true)
    {
        this.strFileName = strFileName;

        // process stream from file
        this.ProcessStream(System.IO.File.Open(strFileName));
    }
    else
       throw new Exception(@"Couldn't find file '" + strFileName);
}

...

private ProcessStream(Stream myStream)
{
    if (filestream != null && filestream.Length > 0 && filestream.CanSeek == true)
    {
        //do stuff
    }
    else
        throw new Exception(@"Couldn't read file from disk.");
}

答案 1 :(得分:4)

我实际上建议公开两个静态方法:

public static DImage FromFile(string filename)
{
    // Load image, then call constructor
}

public static DImage FromData(byte[] data)
{
    // Do anything you need to, then call the constructor
}

构造函数的确切形式取决于您,但我可能会将其设为私有。使用静态工厂方法可以在我的经验中获得更清晰的代码,这意味着您可以推迟调用实际构造函数,直到您真正准备好完成工作为止。这有助于使字段只读等。最大的缺点是缺乏对继承的支持。

答案 2 :(得分:0)

我可以想象实现3个构造函数:

  1. 接受System.Stream
  2. 可以访问的System.IO.StreamReader
  3. 接受一个字节数组,将其包装到System.IO.MemoryStream并调用第一个构造函数。
  4. 接受文件名,使用System.IO.FileStream加载并调用第一个构造函数。
  5. 以下是一个例子:

    using System.IO;
    
    // ...
    
    public DImage(Stream Stream)
    {
        using (var reader = new StreamReader(Stream))
        {
            // Read the image.
        }
    }
    
    public DImage(byte[] Bytes) 
        : this(new MemoryStream(Bytes))
    {
    }
    
    public DImage(string FileName) 
        : this(new FileStream(FileName, FileMode.Open, FileAccess.Read))
    {
    }
    

    这也使得处理异常变得更容易。如果文件不存在,FileStream的构造函数将抛出System.IO.FileNotFoundException,因此您可以从实例化DImage - 类的任何地方处理它:

    try
    {
        var image = new DImage(@"C:\Test.img");
    }
    catch (System.IO.FileNotFoundException e)
    {
        // The image could not be found.
    }
    catch (Exception e)
    {
        // Something else happened.
    }
    

    此方法使用构造函数后面的关键字this将特殊构造案例委托给默认构造函数。它有两个优点:

    1. 删除代码douples,以减少所需的代码。
    2. 通过定义默认构造函数,提高可重用性,接受System.Stream。客户端可以调用构造函数从内存块或文件系统条目加载图像,也可以实现自己的流来提供自定义数据源(如DB BLOB,NetworkStreams,......)。