【C#进阶】C# 属性

序号系列文章
12【C#基础】C# 文件与IO
13【C#进阶】C# 特性
14【C#进阶】C# 反射

前言

🌲 大家好,我是writer桑,本章为大家介绍 C# 中的属性


1,属性的概念

属性是 C# 中的重要成员。 属性和字段1类似,但属性提供了一种被称为访问器的灵活机制来读取、写入或计算私有字段的值。访问器是用于定义访问属性或为属性赋值时执行的语句。借助属性所定义的语法,开发者可写出兼具安全性与灵活性的代码。

2,属性的定义

属性的定义和字段类似,可以说是字段的自然延伸。属性定义包含 get 和 set 访问器的声明,其中 set 访问器可分配数据成员,get 访问器检索数据成员值。

代码示例:

using System;

public class Person
{
    public string name { get; set; } 

    static void Main(string[] args)
    {
        Person p = new Person();
        if(p.name == null)
        {
            Console.WriteLine("Person类的name属性的值为空。");
        }
        else
        {
            Console.WriteLine($"Person类的name属性的值为{p.name}。"); 
        }
    }
}

运行结果:
在这里插入图片描述
在上例中演示了属性定义中最简单的一种情况,不需要对访问器进行验证的读写属性。

2.1 设置初始化值

在 C# 中,属性支持在定义时设置除了默认值以外的值,可以通过在属性的右括号后设置初始值。

可以在前面示例中的 Person 类的基础上对 name 属性进行初始化赋值。

代码示例:

public string name { get; set; } = "personName";

运行结果:
在这里插入图片描述
在上例中,对 name 属性设置了初始化值 personName 。

3,访问器的使用

属性的访问器是一个包含有助于计算、写入或读取属性的可执行语句,其中包含 get 和 set 访问器。 当对属性进行写入值的时候,程序执行的是 set{} 中的语句,当想要读取属性中的值的时候,程序执行的是 get {} 中的语句。

在实际的项目中,可以根际不同的需求在访问器中编写所需的代码,以此创建多种不同的验证行为。

代码示例:

using System;

public class TimeExample
{
    private double _seconds;
    public double Hours
    {
        get { return _seconds / 3600; }
        set
        {
            if (value < 0 || value > 24)
                throw new ArgumentOutOfRangeException(nameof(value),
                "有效范围为0 ~ 24。");
            _seconds = value * 3600;
        }
    }
}

public class Program
{
    static void Main(string[] args)
    {
        TimeExample time = new TimeExample() { Hours = 12 };
        Console.WriteLine($"TimeExample类的Hours属性值为{time.Hours}");
    }
}

运行效果:
在这里插入图片描述
在上例中,定义了 Hours 属性,在读取属性值方面设置了 value 值必须是在0到24的范围之内的条件,否则会引发编译器错误,这就是属性中访问器的使用。

4,访问权限限制

在 C# 中,属性的访问权限2并不是唯一的。可以创建只读属性,或者对 set 和 get 访问器提供不同的可访问性。在 set 和 get 访问器的定义前放置访问修饰符,以此来实现比在属性定义上的访问修饰符更严格的限制。其中允许放置的访问修饰符有 public、private、protected、internal 、protected internal 和 private protected。

代码示例:

using System;

public class Person
{
    private string _firstName;

    public string FirstName
    {
        get { return _firstName; }
        set
        {
            if (string.IsNullOrWhiteSpace(value))
                throw new ArgumentException("名字不能为空");
            _firstName = value;
        }
    }

    // 类成员的实现 ....
}

public class Program
{
    static void Main()
    {
        Person p = new Person() { FirstName = "Adelina" };
        Console.WriteLine($"Person类的FirstName属性值为{p.FirstName}"); 
    }
}

运行结果:
在这里插入图片描述

在上例中,Person 类中定义了私有属性 _firstName。Person 类只能从该类的其他方法中启用 FirstName 属性值改写和读取 _firstName 属性。 _firstName 属性前面定义 private 访问修饰符,说明只有同一类或结构体中的代码才可以访问该类型或成员

5,只读属性

在属性中可以只定义 get 访问器,而不定义 set 访问器,那么这个属性就是只读属性3。但是属性不能不定义 get 访问器,会引起编译器报错。

代码示例:

using System; 

public class Person
{
    public Person(string firstName) => FirstName = firstName;
    public string FirstName { get; }        // 只读属性 

    // 省略实现其它类成员...
}

public class Program
{
    static void Main()
    {
        string firstName = "Rosalind";
        Person p = new Person(firstName);
        Console.WriteLine(p.FirstName);
    }
}

运行结果:
在这里插入图片描述

当定义属性时不写 get 访问器时,编译器会报错。

代码示例:

public string FirstName { set; }        // 只读属性 

代码效果:
在这里插入图片描述

6,初始化访问器

在调用上例中的只读属性时,调用方无法使用对象初始值设定项向属性分配值。若要支持初始值设定项,可以将 set 访问器设置为 init 访问器

代码示例:

using System;

public class Person
{
    public Person() { }
    public Person(string firstName) => FirstName = firstName;
    public string FirstName { get; init; }

    // 省略实现其它类成员...
}

public class Program
{
    static void Main()
    {
        Person p = new Person() { FirstName = "Rosalind" };
        Console.WriteLine($"Person类的Firstname属性值为{p.FirstName}");
    }
}

运行结果:
在这里插入图片描述

在上例中,不必通过 Person 类的构造函数来对属性赋值。在实现 init 访问器的基础上就可以使用对象初始值设定项向属性分配值。

7,抽象属性

在抽象类4中,不仅可以有抽象方法,还可以有抽象属性。抽象属性的声明不提供属性访问器的实现,它声明该类支持属性,而将访问器实现留给派生类。也就是抽象属性应在派生类中被实现。

代码示例:

using System;

public abstract class Person
{
    public abstract string Name { get; set; }
    public abstract int Age { get; set; }
}

public class Student : Person
{
    private string code = "11";
    private string name = "Adelina";
    private int age = 0;

    // 声明类型为 string 的 Code 属性
    public string Code
    {
        get
        {
            return code;
        }
        set
        {
            code = value;
        }
    }

    // 声明类型为 string 的 Name 属性
    public override string Name
    {
        get
        {
            return name;
        }
        set
        {
            name = value;
        }
    }

    // 声明类型为 int 的 Age 属性
    public override int Age
    {
        get
        {
            return age;
        }
        set
        {
            age = value;
        }
    }

    public override string ToString()
    {
        return "Name = " + Name + ", Age =" + Age + ", Code = " + Code; 
    }
}

public class Example
{
    public static void Main()
    {
        // 创建一个新的 Student 对象
        Student s = new Student();

        s.Code = "21004200";
        s.Name = "Rosalind";
        s.Age = 21;
        Console.WriteLine($"学生信息:- {s}");
    }
}

代码效果:
在这里插入图片描述
在上例中,抽象类 Person 中声明了抽象属性 Name 和 Age,派生类 Student 在继承 Person 之后重写了这两个属性,并进行打印输出。

8,接口属性

和抽象属性类似,属性也可以在接口5上进行声明。接口属性一般没有主体,和类和结构体不同,在没有主体的情况下声明访问器不会声明自动实现的属性。接口属性可以定义默认实现,但是这样的情况非常少。

代码示例:

interface IEmployee
{
    string Name { get; set; }
    int Counter { get;  }
}

public class Example : IEmployee
{
    public static int numberOfEmployees;

    private string _name;
    public string Name  //读写实例属性 
    {
        get { return _name; }
        set { _name = value; }
    }

    private int _counter;
    public int Counter  //只读实例属性
    {
        get { return _counter; } 
    }

    // 构造函数 
    public Example() { _counter = ++numberOfEmployees; } 
}

public class Program
{
    static void Main(string[] args)
    {
        Example e = new Example() { Name = "Rosalind" };
        Console.WriteLine($"接口属性信息, name:{e.Name}, Count:{e.Counter}"); 
    }
}

代码效果:
在这里插入图片描述

点击了解更多属性的使用。


结语

🌳 以上就是 C# 属性的介绍啦,希望对大家有所帮助。感谢大家的支持。


  1. 字段:是在类或结构中直接声明的任意类型的变量。 字段也是类中包含类型的成员。 ↩︎

  2. 访问权限:控制是否可以从你的程序集或其他程序集中的其他代码中使用它们。 ↩︎

  3. 只读:是指文档或属性只能被读取,不能被修改或存储。 ↩︎

  4. 抽象类:是提供可以由子类共享的一般形式,由子类根据自己的实际情况去处理这个一般形式。 ↩︎

  5. 接口:是包含类或结构可以实现相关一组功能的一个定义。 ↩︎

  • 17
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

哈桑indie

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值