C# C语言中的多个构造函数#

C# C语言中的多个构造函数#,c#,constructor,C#,Constructor,我有一个需要数据的类,可以是字节,也可以是文件路径 此时,我将文件读入字节数组,然后设置类。在另一个分隔符中,它直接从作为参数传递的字节设置类 我希望第一个构造函数(文件路径)调用第二个(字节),类似于: public DImage(byte[] filebytes) : this() { MemoryStream filestream = null; BinaryReader binReader = null; if (fileb

我有一个需要数据的类,可以是字节,也可以是文件路径

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

我希望第一个构造函数(文件路径)调用第二个(字节),类似于:

    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);

    }

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

您可以创建一个私有方法,将
字节[]
作为参数,例如
ProcessImage(byte[]myparam)
,这将由两个构造函数调用以处理您的字节

旁注:您可能需要考虑使用<代码>流>代码>而不是<代码>字节[]/Calp>.P/>


快速示例:

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.");
}

您可以创建一个私有方法,将
byte[]
作为参数,比如
ProcessImage(byte[]myparam)
,这将由两个构造函数调用以处理您的字节

旁注:您可能需要考虑使用<代码>流>代码>而不是<代码>字节[]/Calp>.P/>


快速示例:

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.");
}

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


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

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


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

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

  • 接受可由访问的
  • 接受字节数组,将其包装成一个数组并调用第一个构造函数
  • 接受文件名,使用加载并调用第一个构造函数
  • 下面是一个例子:

    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
    ,将特殊构造案例委托给默认构造函数。它有两个优点:

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

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

  • 接受可由访问的
  • 接受字节数组,将其包装成一个数组并调用第一个构造函数
  • 接受文件名,使用加载并调用第一个构造函数
  • 下面是一个例子:

    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
    ,将特殊构造案例委托给默认构造函数。它有两个优点:

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

  • 所以你的问题是什么?我似乎漏掉了:)我如何调用第一个构造函数?@Jonathan。你不能用这种方式调用chain构造函数。我的意思是,第一个调用第二个的结果,结果是字节数组。您必须提取方法中的逻辑并手动调用它们。您不能从方法体中调用另一个构造函数,只能在冒号之后,例如public DImage(string strFileName):this()正在调用默认(无参数)构造函数。您最好将功能提取到一个方法中,并从两个构造函数中调用它,就像ken2k建议的那样。。。你的问题是什么?我似乎漏掉了:)我如何调用第一个构造函数?@Jonathan。你不能用这种方式调用chain构造函数。我的意思是,第一个调用第二个的结果,结果是字节数组。您必须提取方法中的逻辑并手动调用它们。您不能从方法体中调用另一个构造函数,只能在冒号之后,例如public DImage(string strFileName):this()正在调用默认(无参数)构造函数。最好将功能提取到一个方法中,并从两个构造函数中调用它,如ken2ksuggests@Jonathan. 基本上是因为字节[]完全加载到内存中,而流则没有。另一个原因是,它允许人们使用通用且经常使用的流类型调用代码,而不要求他们先将代码转换为byte[],然后再转换回Stream(MemoryStream)。最终,根据您项目的上下文(即,您的代码是否会被除您之外的其他人重用,是库吗?),您可能只希望公开以流作为参数的构造函数,并让使用您的类的代码执行“文件->流”和“字节[]->流”操作