# C# 属性

> 原文： [https://zetcode.com/lang/csharp/properties/](https://zetcode.com/lang/csharp/properties/)

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

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

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

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

`Program.cs`

```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`类。

```cs
public string Name
{
   ...
}

```

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

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

```

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

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

Console.WriteLine(p.Name);

```

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

```cs
$ dotnet run
Jane

```

这是该计划的结果。

## C# 只读属性

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

`Program.cs`

```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);
        }
    }
}

```

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

```cs
private string _name = "Jane";

```

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

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

```

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

```cs
// 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`

```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`类，其中有两个属性：`Name`和`Age`。

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

```

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

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

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

```

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

```cs
$ dotnet run
Jane is 17 years old

```

这是示例的输出。

## 表达式主体定义

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

`Program.cs`

```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`类的属性。

```cs
$ dotnet run
John Doe is a gardener

```

这是输出。

## 其他注意事项

我们可以使用`public`，`private`或`protected`等访问修饰符标记属性。 属性也可以是`static`，`abstract`，`virtual`和`sealed`。 它们的用法与常规方法相同。

`Program.cs`

```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`类中将其覆盖。

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

```

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

```cs
protected new string _name = "Derived class"; 

```

我们将成员隐藏在“派生”类中。 为了消除编译器警告，我们使用`new`关键字。

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

```

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

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