跳转至

C# 属性

原文: https://zetcode.com/lang/csharp/properties/

在 C# 教程的这一部分中,我们将讨论属性。

属性是一种特殊的类成员。 我们使用预定义的设置和获取方法来访问和修改它们。 属性读取和写入会转换为获取和设置方法调用。 与使用自定义方法调用(例如object.GetName())相比,使用字段符号(例如object.Name)访问变量更容易。 但是,就属性而言,我们仍然具有封装和信息隐藏的优势。 换句话说,属性可以保护数据免受外界干扰,同时可以方便地进行现场访问。

接口可以具有属性,但不能具有字段。

属性可以是读写的(它们既有获取和设置访问器),也可以是只读的(它们只有获取访问器)或只写(它们只有设置访问器)。

Program.cs

using System;

namespace SimpleProperties
{
    class Person
    {
        private string _name;

        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var p = new Person();
            p.Name = "Jane";

            Console.WriteLine(p.Name);
        }
    }
}

我们有一个具有一个属性的简单Person类。

public string Name
{
   ...
}

我们有一个称为Name的属性。 它看起来像一个常规方法声明。 不同之处在于,它具有称为getset的特定访问器。

get { return _name; }
set { _name = value; } 

get属性访问器用于返回属性值,set访问器用于分配新值。 value关键字用于定义由设置索引器分配的值。

var p = new Person();
p.Name = "Jane";

Console.WriteLine(p.Name);

我们创建Person类的实例。 我们使用字段符号访问成员字段。

$ dotnet run
Jane

这是该计划的结果。

C# 只读属性

可以创建只读属性。 为了创建一个只读属性,我们省略了 set 访问器,在实现中仅提供了 get 访问器。

Program.cs

using System;

namespace Readonly
{
    class Person
    {
        private string _name = "Jane";

        public string Name
        {
            get { return _name; }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var p = new Person();
            // p.Name = "Beky";

            Console.WriteLine(p.Name);
        }
    }
}

在前面的示例中,我们演示了只读属性的使用。

private string _name = "Jane";

我们立即初始化成员,因为以后不可能。

public string Name
{
    get { return _name; }
}

通过仅提供一个 get 访问器,使该属性为只读。

// p.Name = "Beky";

现在此行已注释。 我们无法更改属性。 如果我们取消注释该行,则 C# 编译器将发出以下错误:Program.cs(21,13): error CS0200: Property or indexer 'Person.Name' cannot be assigned to -- it is read only

C# 自动实现的属性

C# 具有自动实现或自动属性。 在软件项目中,有许多简单属性只能设置或获取一些简单值。 为了简化编程并简化代码,创建了自动属性。 注意,我们不能在所有情况下都使用自动属性。 仅适用于简单的。

Program.cs

using System;

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

    class Program
    {
        static void Main(string[] args)
        {
            var p = new Person();
            p.Name = "Jane";
            p.Age = 17;

            Console.WriteLine($"{p.Name} is {p.Age} years old");
        }
    }
}    

该代码要短得多。 我们有一个Person类,其中有两个属性:NameAge

public string Name { get; set; }
public int Age { get; set; }

在这里,我们有两个自动属性。 没有访问器的实现,也没有成员字段。 编译器将为我们完成其余的工作。

var p = new Person();
p.Name = "Jane";
p.Age = 17;

Console.WriteLine($"{p.Name} is {p.Age} years old");

我们通常照常使用这些属性。

$ dotnet run
Jane is 17 years old

这是示例的输出。

表达式主体定义

从 C# 7.0 开始,可以使用表达式主体定义简化属性。 表达式主体定义由=>符号组成,后跟要分配给该属性或从该属性检索的表达式。

Program.cs

using System;

namespace ExpBodyDef
{
    class User
    {
        string name;
        string occupation;

        public User(string name, string occupation)
        {
            this.name = name;
            this.occupation = occupation;
        }

        public string Name
        {
            get => name;
            set => name = value;
        }

        public string Occupation
        {
            get => occupation;
            set => occupation = value;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var u = new User("John Doe", "gardener");

            Console.WriteLine($"{u.Name} is a {u.Occupation}");
        }
    }
}

在示例中,我们使用表达式主体定义来定义User类的属性。

$ dotnet run
John Doe is a gardener

这是输出。

其他注意事项

我们可以使用publicprivateprotected等访问修饰符标记属性。 属性也可以是staticabstractvirtualsealed。 它们的用法与常规方法相同。

Program.cs

using System;

namespace OtherNotes
{
    class Base
    {
        protected string _name = "Base class";

        public virtual string Name
        {
            set { _name = value; }
            get { return _name; }
        }
    }

    class Derived : Base
    {
        protected new string _name = "Derived class";

        public override string Name
        {
            set { _name = value; }
            get { return _name; }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var bs = new Base();
            var dr = new Derived();

            Console.WriteLine(bs.Name);
            Console.WriteLine(dr.Name);
        }
    }
}

在前面的示例中,我们定义了一个虚拟属性,并在Derived类中将其覆盖。

public virtual string Name
{
    set { _name = value; }
    get { return _name; }
}

名称属性用virtual关键字标记。

protected new string _name = "Derived class"; 

我们将成员隐藏在Derived类中。 为了消除编译器警告,我们使用new关键字。

public override string Name
{
    set { _name = value; }
    get { return _name; }
}

在这里,我们重写了Base类的Name属性。

本章介绍了 C# 属性。 我们描述了属性并显示了如何实现它们。 我们提到了自动属性和只读属性。



回到顶部