设置常量对象变量的字段

时间:2014-03-31 17:21:02

标签: c#

我正在创建一个类来对整个应用程序中使用的所有常量变量进行分组,并且有两个类型为PictureBox的Object变量。

例如:

public const PictureBox availablePic = new PictureBox();
public const PictureBox unavailablePic = new PictureBox();

但是如果我将它们声明为常量,那么我必须将它们设置为整个应用程序中的内容,这就是我想要为Image属性做的事情。

所以我的问题是,如何在声明中声明我的Object类型常量的属性?

我主要是一名Java程序员,所以我正在寻找如何在C#中以正确的方式做到这一点。

6 个答案:

答案 0 :(得分:2)

你不能用可变引用类型(PictureBox是)来做到这一点。您可以使用readonly,但在这种情况下,引用将是只读的。没有什么可以阻止客户端更改引用对象的属性(这将影响具有相同引用的所有其他客户端)。

无法创建无法更改的PictureBox。如果你想返回一个"常数" 图像 只读。您还可以提供只读属性,它将新的PictureBox引用集返回到"常量"图片。这样,如果客户更改了一个PictureBox,则其他人不受影响。

private readonly Image availablePic ;
private readonly Image unavailablePic ;

// initialize images in static constructor

public static PictureBox UnavailablePic
{
   get{
       return new PictureBox {Image = unavailablePic};
   }
}

public static PictureBox AvailablePic
{
   get{
       return new PictureBox {Image = availablePic};
   }
}

答案 1 :(得分:2)

如评论中所示,对于任何非原始变量,const关键字都不起作用。相反,您可以使用staticreadonly关键字的组合。

要初始化它们,请使用它们的构造函数,对象初始值设定项或向类中添加静态构造函数。考虑到您选择的对象,静态构造函数可能是最好的。静态构造函数的工作方式与对象构造函数类似,但在第一次使用类时只运行一次。它们专门用于初始化静态组件。

要声明一个,请在看似无参数构造函数的前面使用static关键字(再次)。例如:static MyClass()

因此,您的代码可能类似于:

class MyClass
{
   public static readonly PictureBox availablePic = new PictureBox();
   public static readonly PictureBox unavailablePic = new PictureBox();

   static MyClass()
   {
      // Initialize the picture boxes here.
      availablePic.Image = Image.FromFile("available.png");
   }

...
}

答案 2 :(得分:1)

您需要使用readonly,而不是const,因为您要分配的内容不是编译时字面值。要初始化数据,您有几个选项:

  1. 使用对象初始值设定项:

    public static readonly PictureBox box = new PictureBox() { Value = "sample" };
    
  2. 使用静态方法初始化对象:

    public static readonly PictureBox box = CreatePicturebox();
    
    public static PictureBox CreatePicturebox()
    {
        PictureBox box = new PictureBox();
        box.Value = "sample";
        return box;
    }
    
  3. 使用静态构造函数

    public class Foo
    {
        public static readonly PictureBox box;
    
        static Foo()
        {
            box = new PictureBox();
            box.Value = "sample";
        }
    }
    
  4. 另请注意,如果PictureBox是一个可变类型,那么创建此字段readonly只意味着永远不能更改引用以引用另一个对象。 not 意味着对象本身不能被改变。您希望将对象设为不可变,或者提供一个公开公开的不可变包装器,如果这是您的意图。

答案 3 :(得分:1)

const仅适用于文字(例如1"foo")。您需要的是static readonly,它标记了类型可访问的字段,并且引用不可修改。 (我会使用Image代替PictureBox,因为PictureBox是winforms控件而不是数据。)

public static class Constants
{
    public static readonly Image AvailablePic =
        (Image)Resources.ResourceManager.GetObject("AvailablePic");
    public static readonly Image UnavailablePic =
        (Image)Resources.ResourceManager.GetObject("UnavailablePic");
}

这样您就可以引用代码中的字段:

var pic = Constants.AvailablePic;

但是,如果您需要在应用程序初始化之前加载这些值,我将避免使用static readonly,而是使用仅具有getter的接口:

public interface IConfiguration
{
    public Image AvailablePic { get; }
    public Image UnavailablePic { get; }
}

public class Configuration : IConfiguration
{
    public Configuration(Image availablePic, Image unavailablePic)
    {
        AvailablePic = availablePic;
        UnavailablePic = unavailablePic;
    }

    public Image AvailablePic { get; private set; }
    public Image UnavailablePic { get; private set; }
}

这样您就可以将IConfiguration传递给需要此信息的对象。

e.g。在WinForms项目中,您可以将其传递给表单类构造函数。

public class MainForm : Form
{
    private readonly IConfiguration _configuration;

    public MainViewModel(IConfiguration configuration)
    {
        InitializeControls();
        _configuration = configuration;
    }

    public void MakeAvailable(object sender, EventArgs e)
    {
        PictureBox.BackgroundImage = _configuration.AvailablePic;
    }

    public void MakeUnavailable(object sender, EventArgs e)
    {
        PictureBox.BackgroundImage = _configuration.UnavailablePic;
    }
}

答案 4 :(得分:0)

使用只允许一项作业的readonly关键字,例如

public readonly PictureBox availablePic = new PictureBox() {
  // Put all required properties here
  BackColor = Color.AliceBlue,
  BorderStyle = BorderStyle.FixedSingle,
  ...
};

public readonly PictureBox unavailablePic = new PictureBox();

答案 5 :(得分:0)

如果公开PictureBox,消费代码可以更改其Image。没办法解决它。如果您想在不让消费代码访问其Image属性的情况下显示PictureBox,那么您唯一的办法就是将其封装在您自己的自定义控件中。