这样子可以绕开属性get和set限制,那么字段与属性的访问级别岂不是不保险

addisjeams 2016-03-06 03:29:03
有一个小问题,问问路过的漫天诸佛各位大神.

如下:

主窗口


private ArrayList listData1;

public ArrayList hsListData1
{
get { return this.listData1; }
}
public Form1()
{
InitializeComponent();
this.listData1 = new ArrayList();
this.listData1.Add("DotNet");
this.listData1.Add("C#");
this.listData1.Add("Asp.net");
this.listData1.Add("WebService");
this.listData1.Add("XML");
this.listBoxFrm1.DataSource = this.listData1;
}

private void buttonEdit_Click(object sender, System.EventArgs e)
{
Form2 formChild = new Form2();
formChild.Owner = this;
formChild.ShowDialog();
this.listBoxFrm1.DataSource = null;
this.listBoxFrm1.DataSource = this.listData1;
}





子窗体

private ArrayList listData2;//接收来自form1的数据

public Form2()
{
InitializeComponent();
}

//记得要在form2的"事件"里面添加这个
//之所以没有放到form2的构造函数,是因为有逻辑问题,会有null引用产生
private void Form2_Load(object sender, System.EventArgs e)
{
Form1 pareForm = (Form1)this.Owner;
this.listData2 = pareForm.hsListData1;
foreach (object o in this.listData2)
{
this.listBoxFrm2.Items.Add(o);
}
}
private void buttonAdd_Click(object sender, System.EventArgs e)
{
if (this.textBoxAdd.Text.Trim().Length > 0)
{
this.listData2.Add(this.textBoxAdd.Text.Trim());
this.listBoxFrm2.Items.Add(this.textBoxAdd.Text.Trim());
}
else
MessageBox.Show("请输入添加的内容!");
}
private void buttonOK_Click(object sender, System.EventArgs e)
{
this.Close();
}



稍微说一下,也就是主窗体通过
Form2 formChild = new Form2();
formChild.Owner = this;
与被调用的form发生联系,然后被调用的form被调用后,通过主窗体中的属性hsListData1修改了字段listData1的值
现在问题来了-----------主窗体的属性只有get,如果我加上private set也是没有用的.都可以被写!
问问这是怎么一回事?
不是说属性get 和set 可以保护类下的字段值么?
如果不能保证属性的get与set的有效性, 类的属性存在岂不是毫无意义?

...全文
202 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
Lee_Y_K 2016-03-06
  • 打赏
  • 举报
回复
引用 11 楼 lovelj2012 的回复:
做了下测试,#8的假设是正确的
class Users
    {
        public string Username { get; set; }
        public string Stu_number { get; set; }
    }

    class UserInfo
    {
        public List<Users> ListUser { get; private set; }

        public UserInfo()
        {
            ListUser = new List<Users>();
            ListUser.Add(new Users { Username = "Jimmy", Stu_number = "00009099" });
        }

        public void Print()
        {
            foreach (Users user in ListUser)
            {
                Console.WriteLine(user.Username + "--" + user.Stu_number);
            }
        }
    }
static void Main(string[] args)
        {
            UserInfo ui = new UserInfo();
            ui.Print();
            List<Users> lstUser = ui.ListUser;
            foreach (Users user in lstUser)
            {
                user.Username = "刘德华";
                user.Stu_number = "00009091";
            }
            ui.Print();

            Console.ReadKey();
        }
#8 的方法或许可以满足你的需求,但是你要考虑一个问题,每一次访问属性的时候都会Clone一次,在频繁访问属性时就会出现内存泄露的问题. @sp1234
江南小鱼 2016-03-06
  • 打赏
  • 举报
回复
做了下测试,#8的假设是正确的
class Users
    {
        public string Username { get; set; }
        public string Stu_number { get; set; }
    }

    class UserInfo
    {
        public List<Users> ListUser { get; private set; }

        public UserInfo()
        {
            ListUser = new List<Users>();
            ListUser.Add(new Users { Username = "Jimmy", Stu_number = "00009099" });
        }

        public void Print()
        {
            foreach (Users user in ListUser)
            {
                Console.WriteLine(user.Username + "--" + user.Stu_number);
            }
        }
    }
static void Main(string[] args)
        {
            UserInfo ui = new UserInfo();
            ui.Print();
            List<Users> lstUser = ui.ListUser;
            foreach (Users user in lstUser)
            {
                user.Username = "刘德华";
                user.Stu_number = "00009091";
            }
            ui.Print();

            Console.ReadKey();
        }
addisjeams 2016-03-06
  • 打赏
  • 举报
回复
引用 7 楼 tcmakebest 的回复:
get,set 操作属性只是提供了一种可控的机制,让外部通过这个机制存或取数据, 通道上可以编写代码筛选数据(set时),或者编写代码伪造数据(get时), 楼主需要保护数据那得自己来写代码的,这里的问题在于get得到的数据本身带有一些方法可以改变数据,那就要在 get 的时候不提供原始数据,而是提供"复印件",如下,但如果里面存储的不是简单数据类型,仅是 Clone 还是有被修改的风险.
public ArrayList hsListData1
{
    get { return (ArrayList)this.listData1.Clone(); }
}
谢谢你的回复, 结帖时候,漏掉你了,sorry一下.....
addisjeams 2016-03-06
  • 打赏
  • 举报
回复
谢谢大家的回复 这个问题,我主要是关心 一个就是get和set能否保证属性或者说属性所引用的字段能否被限定读写能力. 实际上,就我举的这个例子,get是可以的,set本身是不行的, 就如同楼上所说,因为字段本身有方法,可以对它引用后进行处理.所以也就变相的set了. 在实际工作中,这个必须避免才好,或者说必须检查,慎重选择. 结帖, 感谢大家.
江南小鱼 2016-03-06
  • 打赏
  • 举报
回复
撸主描述的只读属性(get)对应的私有字段被修改了,说实话哥从来没注意过。如果你说的属实(我没去验证),那么就是说通过属性获取到的是变量的地址,对这个地址存储的修改,反映到原变量了。
tcmakebest 2016-03-06
  • 打赏
  • 举报
回复
get,set 操作属性只是提供了一种可控的机制,让外部通过这个机制存或取数据, 通道上可以编写代码筛选数据(set时),或者编写代码伪造数据(get时), 楼主需要保护数据那得自己来写代码的,这里的问题在于get得到的数据本身带有一些方法可以改变数据,那就要在 get 的时候不提供原始数据,而是提供"复印件",如下,但如果里面存储的不是简单数据类型,仅是 Clone 还是有被修改的风险.
public ArrayList hsListData1
{
    get { return (ArrayList)this.listData1.Clone(); }
}
Lee_Y_K 2016-03-06
  • 打赏
  • 举报
回复
如果你不想其他地方通过主窗体的listData1属性来改变集合的值,你可以把listData1属性换成枚举(IEnumerable)类型
Lee_Y_K 2016-03-06
  • 打赏
  • 举报
回复
引用 4 楼 u012758945 的回复:
晕啊,你先理解清楚。 hsListData1 这个属性代表只能get,也就是不能设置“主窗口”的hsListData1 属性,但是可以获取。 获取到的hsListData1 可以调用Add方法,因为ArrayList 的Add方法是公共的。 不明白我打个比方, 你的钱包里有个【位置】放在一张卡号是xxxx的银行卡,你只能拿来用(可以 get), 但这个【位置】不能换成其他号码的卡(不能 set) 你拿到这张卡在用的时候,里面的钱可以随便【刷】或【存】(因为卡里的钱可以get;set;),明白了没有。
当你用了这张卡,前面的余额会改变,但是卡还是你原来那张卡。
Lee_Y_K 2016-03-06
  • 打赏
  • 举报
回复
晕啊,你先理解清楚。 hsListData1 这个属性代表只能get,也就是不能设置“主窗口”的hsListData1 属性,但是可以获取。 获取到的hsListData1 可以调用Add方法,因为ArrayList 的Add方法是公共的。 不明白我打个比方, 你的钱包里有个【位置】放在一张卡号是xxxx的银行卡,你只能拿来用(可以 get), 但这个【位置】不能换成其他号码的卡(不能 set) 你拿到这张卡在用的时候,里面的钱可以随便【刷】或【存】(因为卡里的钱可以get;set;),明白了没有。
  • 打赏
  • 举报
回复
打个比方吧。你家里有个门,门上有把锁防小偷。现在你把儿子派出去给你打酱油去了,结果儿子被人偷走了,你还来找卖你门锁的商户理论吗? 这不行的。这跟门锁没有关系,是你提供给小偷的机会,人家卖锁的商户也没有办法啊。
  • 打赏
  • 举报
回复
我没有看你的代码,只看了你的标题,因为你贴的代码实在是太多了。如果有什么问题跟上述回答的范畴不一致的,请说出来。 就你的标题的问题来说,当推荐一种更好的、更规范的语法写法的时候,都是正向思维、善意推荐。不保证有人另辟蹊径。
  • 打赏
  • 举报
回复
晕。编程语言、编程平台是工具,你要是不喜欢,可以用汇编语言,难道你能因此说 c#、vb.net 语言“起步时没用么”? 不要一味只用反叛式的思维方式来学习。get、set 就是提供了比传统的读写字段更好的语法工具,不是用来惩罚那些幼稚的罪犯的,它不保证别的。

111,129

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Creator Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧