10 属性(property)

本文详细介绍了C#中的属性(property)概念及其使用方法,包括自动实现的属性与手动实现的get/set方法,并探讨了属性在序列化过程中的注意事项。此外,还介绍了匿名类型的使用场景及限制条件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

想对于【java/c++】这些语言来说,c#的property是比较独特的。给 使用者一种介于方法和字段之间的感觉【对于编译器而言,其实还是一个字段+get/set两个方法】

属性【property】,使用起来还是比较简单的:

public sealed class PropertyDemo{
    public string Name{get;set;}
    ...
}

个人比较喜欢这种方式,另外常见的也有:

public sealed class PropertyDemo{
    private string name;
    public string Name{
        get{
            return name;
        }
        set{
            name = value;
        }
    }
    ...
}

其实,个人觉得不是很有必要,如果用了属性再写一个私有字段,这和直接去写get/set有区别吗?以最开始那种方式书写方便如果有需要也可以再加进去,使用端代码也不需要有什么变化。最开始那种方式中,使用了C#提供的AIP【自动完成属性】功能,大多数时候这样做就够了,但是,如果对于值有某些要求,比如Age属性,不希望输入值不合法,就可以这样做:

        private int age;
        public int Age
        {
            get
            {
                return age;
            }
            set
            {
                if (Age < 0)
                {
                    throw new ArgumentException("Age should greater than 0");
                }
                age = value;
            }
        }

当自己实现了set体时,就必须也实现get体。【要么都不实现,要么都实现】
也可以对get/set进行访问控制【只要比属性本身的访问控制严格就行】
总体上说来,使用上是比较简单的,用法上不多说。需要注意的是:
在使用AIP时,编译器会产生一个字段,和两个get/set方法。因此,如果对某个类型要进行序列化/反序列化时,应当注意,由于每次编译,编译器可能产生的字段名称不同,很有可能导致,反序列化失败。
ps: 大多数时候我们很难将字段给予public权限【不符合OO封装】,但是经常性的需要一些get/set方法进行辅助访问【想想java语言一些dto对象】,这确实看起来很不“优雅”,而属性却可以“完美”的解决【编译器把丑陋的地方自己做了】。

对象和初始化器

Student s = new Student(){Name = "xiaolu",Age = "23"};

匿名类型
匿名类型在linq中用的比较多。

var o = new {Name = "xiaolu",Age = "23"};

用到了隐式类型var,因为匿名类型编译器会产生一个类型,这个类型编程者是无法直接获取的。匿名类型无法用返回和参数传递【即使参数类型为object,所有匿名类型也是Object的子类,但是传递进来后,,如何转型?】无法成为返回值也是同样道理,返回类型是不可知的。不过也是可以变通下使用:

 public dynamic func(){
     return new {Name="xiaolu",Age=23};
 }

//Main
//在这里,var或者dynamic关键字都是可以的
dynamic d = func();
//d.Name = "xiaozhang"
//需要注意的是,匿名类型是只读的,上面这句赋值,会造成运行时崩溃。
System.Console.WriteLine(d.Name + " " + d.Age);
//此处即使使用var接收返回值,也是没有智能提示的。

说到匿名类型只读,顺带提下元组类型【System.Tuple】,元组的所有属性也是只读的。
给一个元组的例子,可以体会下用法:

 public static Tuple<int, int> MinMax(int a, int b)
 {
     return new Tuple<int, int>(System.Math.Min(a, b), System.Math.Max(a, b));
 }
//Main
var mm = Demo.MinMax(5, 2);
System.Console.WriteLine("min is {0} ,max is {1}", mm.Item1, mm.Item2);

需要注意的是:元组的数据是以ItemN【N是参数数目】,如果对于元组的输入超过8个,可以使用元组的Create函数再次创建一个元组。

 public static Tuple<int, int,int,int,int,int,int,Tuple<int,int>> show(int a, int b,int c,int d ,int f,int g,int h,int k,int j)
 {
            return new Tuple<int, int, int, int, int, int, int, Tuple<int, int>>(a, b, c, d, f, g, h, Tuple.Create(k, j));
 }
//Main

var t = Demo.show(1, 2, 3, 4, 5, 6, 7, 8, 9);
            System.Console.WriteLine(t.Item1 +"" + t.Item2 + t.Item3 + t.Item4 + t.Item5 + t.Item6 + t.Item7 + t.Rest.Item1 + t.Rest.Item2);//输出  123456789

写完这个,,确实灰常痛苦。不过这里就是把用法记录下来,万一某天某个家伙不嫌麻烦这样写了呢?- -
补充一点,Tuple也可以使用泛型:

 public static Tuple<T, T> tuple<T>(T a, T b)
 {
     return new Tuple<T, T>(a, b);
 }
 //Main
var t2 = Demo.tuple("string", "s");
            System.Console.WriteLine(t2.Item1 + "  " + t2.Item2);
//一看就懂,不做过多解释

痛苦的都写了,,再看一个相对有意思的东西:
System.Dynamic.ExpandoObject类,说它有意思是因为,它和dynamic结合起来可以让c#表现的像python这样的动态语言一样,看段代码:

 dynamic d = new ExpandoObject();
 d.Name = "xiaolu";
 d.Age = 23;
 d.sex = "男";
//....可以继续任意添加

System.Console.WriteLine("Name:{0},Age:{1},Sex={2}", d.Name, d.Age, d.sex);

有点小酷炫 ,美中不足的是,在输出时,依旧是没有智能提示成员的,想想dynamic语义,也只能算了。

上面说了好多,都是关于无参属性【property】相关的东西,最后为了完整性,说说有参属性【也就是c#中的索引器】,简单的可以看做是对[]操作符的重载。

 class IndexDemo
 {
   private const int max_num = 20;
   //简单起见,给个固定值
   private string[] ss = new string[max_num];
   private int n = 0;//记录个数
   public string this[int index]
   {
       get
       {
         if (index < 0 || index >= max_num)
         {
            throw new ArgumentOutOfRangeException();
         }
         return ss[index];
      }
      set
      {
         if (index < 0 || index >= max_num)
          {
             throw new ArgumentOutOfRangeException();
          }
          ss[index] = value;

          n++;
      }
   }
}
 //Main
  IndexDemo id = new IndexDemo();
  id[0] = "hello";
  id[2] = "world";
  id[1] = id[2];
  System.Console.WriteLine(id[0] +" " + id[1] + id[2]);

用法相对简单,看看例子。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值