首页 > 编程语言 >C# 属性与结构

C# 属性与结构

时间:2024-04-05 16:11:07浏览次数:22  
标签:Name get C# name 属性 public string 结构

C# 属性

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

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

属性可以是读写的(它们既有 get 和 set 访问器),也可以是只读的(它们只有 get 访问器)或只写(它们只有 set 访问器)。

Program.
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.
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.(21,13): error 0200: Property or indexer 'Person.Name' cannot be assigned to -- it is read only

C# 自动实现的属性

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


Program.
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.
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.
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"; 

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


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

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

结构 (程序优化)

C# 结构,结构是值类型。 该类型由struct关键字定义。 结构与类非常相似。 它们在某些方面有所不同。 结构旨在表示轻量级对象,例如PointRectangleColor等。 在许多情况下,结构可能比类更有效。 结构是值类型,并在堆栈上创建。 注意,像intboolfloat之类的原始数据类型在技术上都是struct类型。

所有struct类型都继承自System.ValueType,并且继承自System.Object。 结构从来都不是抽象的,它们总是被隐式密封的。 因此结构类型不支持继承。 因此,不能将struct数据成员声明为受保护的。 struct定义不允许使用抽象修饰符和密封修饰符。 不允许struct声明无参数的构造函数。

结构还可以包含构造函数,常量,字段,方法,属性,索引器,运算符,事件和嵌套类型。 但是,如果我们需要实现更多这些功能,则可以考虑使用一个类。 结构可以实现接口。 struct可以用作nullable类型,并且可以分配为空值。

简单结构示例

以下示例创建一个简单的结构。


Program.
using System;

namespace SimpleStructure
{
    public struct Point
    {
        private int x;
        private int y;

        public Point(int x, int y)
        {
            this.x = x;
            this.y = y;
        }

        public override string ToString()
        {
            return String.Format("Point x:{0}, y:{1}", x, y);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var p = new Point(2, 5);
            Console.WriteLine(p);
        }
    }
}

该示例创建一个Point结构。 这个点也可以用一个类来表示,但是有了struct,我们的效率更高了。 特别是如果我们处理了很多问题。


public struct Point
{
    ...
}

该结构用struct关键字声明。


public override string ToString()
{
    return String.Format("Point x:{0}, y:{1}", x, y);
}

struct类型不支持继承。 但是,我们可以对方法使用override关键字,struct类型隐式地从中继承。 ToString()方法就是这种情况。


var p = new Point(2, 5);
Console.WriteLine(p);

我们创建Point结构,并在其上调用ToString()方法。


$ dotnet run
Point x:2, y:5

这是示例的输出。

没有new关键字

可以创建不带new关键字的struct类型的实例。


Program.
using System;

namespace NoNewKeyword
{
    public struct Person
    {
        public string name;
        public int age;
    }

    class Program
    {
        static void Main(string[] args)
        {
            Person p;
            p.name = "Jane";
            p.age = 17;

            Console.WriteLine("{0} is {1} years old",
                p.name, p.age);
        }
    }
}

我们有一个Person结构,其中有两个公共成员。

Person p;

首先,我们声明一个Person结构。


p.name = "Jane";
p.age = 17;

稍后我们用一些数据初始化结构。


$ dotnet run
Jane is 17 years old

这是程序的输出。

C# 结构是值类型

结构类型是值类型。 它们是在堆栈上创建的。 创建值类型时,仅在内存中分配了一个空间来存储值。 值类型的分配将复制该值。


Program.
using System;

namespace ValueTypes
{
    public struct Person
    {
        public Person(string name, int age) : this()
        {
            this.Name = name;
            this.Age = age;
        }

        public string Name { get; set; }

        public int Age { get; set; }

        public override string ToString()
        {
            return String.Format("{0} is {1} years old", Name, Age);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var p1 = new Person("Beky", 18);
            var p2 = p1;

            Console.WriteLine(p2);
            p2.Name = "Jane";
            p2.Age = 17;

            Console.WriteLine(p2);
            Console.WriteLine(p1);
        }
    }
}

我们有一个带有两个数据成员的Person结构。 我们有两个参数的构造函数,我们也使用自动属性。


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

可以在struct类型中使用自动属性。

var p1 = new Person("Beky", 18);
var p2 = p1;

在这里,我们创建一个struct。 然后将创建的struct分配给另一个struct。 我们创建该结构的副本。


p2.Name = "Jane";
p2.Age = 17;

我们更改第二个结构的数据。 第一个不受影响,因为我们正在处理原始struct类型的副本。


$ dotnet run
Beky is 18 years old
Jane is 17 years old
Beky is 18 years old

基本类型是结构

intfloatbool之类的原始数据类型是内部结构。 这不同于 C++ 或 Java 之类的语言。


Program.
using System;

public class PrimitiveTypes
{
    static void Main()
    {
        float x = 12.3f;
        int y = 34;
        bool z = false;

        Console.WriteLine(x.GetType());
        Console.WriteLine(y.GetType());
        Console.WriteLine(z.GetType());
    }
}

我们有三个变量:float,intbool。 我们对它们每个调用GetType()方法。

Console.WriteLine(x.GetType());

我们在浮点值上调用GetType()方法。 每个结构都隐式继承自包含GetType()方法的System.ValueType类。


$ dotnet run
System.Single
System.Int32
System.Boolean

这是示例的输出。 我们可以在文档中查找这些类型是结构。

标签:Name,get,C#,name,属性,public,string,结构
From: https://www.cnblogs.com/lvbjj/p/18115851

相关文章

  • 学习记录:bazel和cmake运行终端指令
    Bazel和CMake都是用于构建软件项目的工具,但它们之间有一些重要的区别和特点:Bazel:Bazel是由Google开发的构建和测试工具,用于构建大规模的软件项目。它采用一种称为“基于规则”的构建系统,它利用构建规则和依赖关系来自动化构建过程。Bazel支持多种编程语言,包括C++、Java、......
  • Pdf文件格式解析:stream中的变换矩阵指令 1 0 0 -1 0 841.9 cm
    解释100-10841.9cm在PDF文件中的变换矩阵指令100-10841.9cm中,前四个数值100-1组成了一个2x2的线性变换部分,用于描述旋转和缩放操作,而不涉及平移。这里,100-1的每一个数字都有特定的意义:第一个数字1:这是矩阵的第一行第一列的元素。它决定了x坐标在......
  • 突破编程_C++_网络编程(TCPIP 四层模型(传输层))
    1传输层的功能与作用在TCP/IP四层模型中,传输层位于网络层之上和应用层之下,负责在源主机和目标主机之间提供端到端的可靠数据传输服务。传输层的主要功能与作用体现在以下几个方面:分段与重组:由于网络层的数据包大小有限制(如IP数据包的最大长度为65535字节),而应用层......
  • 突破编程_C++_网络编程(Windows 套接字(概述))
    1什么是Window套接字编程1.1基本概念Windows的套接字(Socket)是基于Windows操作系统的网络通信编程接口。它起源于UNIX系统的Berkeley套接字,但经过微软和第三方厂商的共同制定,形成了一套适用于Windows环境的标准,即WindowsSocket规范,简称WinSock。Windows......
  • 多年前的笔记-CenetOS6.7内核优化
    多年前的笔记-CenetOS6.7内核优化文章目录备份优化内核优化文件描述符数量Centos开机启动优化设置显示主机全名内核优化已完成备份[-f/etc/sysctl.conf]&&cp-av/etc/sysctl.conf{,_bak}优化内核cat>/etc/sysctl.conf<<EOFnet.ipv4.tcp_syn_retrie......
  • Nacos注册中心
    一、Nacos的安装1.1、下载安装包在Nacos的GitHub页面,提供有下载链接,可以下载编译好的Nacos服务端或者源代码:GitHub主页:https://github.com/alibaba/nacosGitHub的Release下载页:https://github.com/alibaba/nacos/releases1.2、解压安装包将这个包解压到任意非中文目......
  • 基于深度学习的PCB电子元件识别系统(网页版+YOLOv8/v7/v6/v5代码+训练数据集)
    摘要:本文深入研究了基于YOLOv8/v7/v6/v5的PCB电子元件识别系统,核心采用YOLOv8并整合了YOLOv7、YOLOv6、YOLOv5算法,进行性能指标对比;详述了国内外研究现状、数据集处理、算法原理、模型构建与训练代码,及基于Streamlit的交互式Web应用界面设计。在Web网页中可以支持图像、视频和实时......
  • C#中的方法
    C#方法定义方法是包含一系列语句的代码块。方法必须在类或结构中声明。好的编程习惯是方法仅执行一项特定任务。方法为程序带来了模块化。正确使用方法具有以下优点:减少代码重复将复杂的问题分解成更简单的部分提高代码的清晰度重用代码信息隐藏C#方法特征方法的......
  • <embed src="../CHANGELOG.md"></embed> 这个的作用是什么
    <embed>标签在HTML中用于嵌入外部内容,比如多媒体文件、插件或其他类型的内容。然而,您提供的代码片段<embedsrc="../CHANGELOG.md"></embed>试图使用embed标签来嵌入一个Markdown文件(CHANGELOG.md),这并不符合embed标签通常的用法。embed标签通常用于嵌入以下类型的资......
  • Property属性使用
    ★基本定义一种用起来像是使用的实例属性一样的特殊属性,可以对应于某个方法★property属性的两种方式装饰器=>在方法上应用装饰器类属性=>在类中定义值为property对象的类属性★装饰器方式代码示例classGoods(object):def__init__(self):......