C# 属性与结构

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/60016.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux系统性能调优技巧详解

Linux系统性能调优技巧详解 在Linux系统中,性能调优是确保系统在高负载下依然能够稳定、高效运行的重要环节。调优的目标包括优化系统资源的利用率(如CPU、内存、磁盘和网络),减少瓶颈,并提升系统的响应速度。本文将深入探讨Linux系统性能调优的技巧,并结合代码使用案例…

视频里的音频怎么提取出来成单独文件?音频提取照着这些方法做

在数字时代,视频与音频的分离与重组已成为日常需求之一。无论是出于制作背景音乐、保存讲座内容,还是编辑播客素材,提取视频中的音频并将其保存为单独文件都显得尤为重要。视频里的音频怎么提取出来成单独文件?本文将详细介绍几种…

基于Canny边缘检测和轮廓检测

这段代码实现了基于Canny边缘检测和轮廓检测,从图像中筛选出面积较大的矩形,并使用OpenCV和Matplotlib显示结果。主要流程如下: 步骤详解: 读取图像: img cv2.imread(U:/1.png)使用cv2.imread()加载图像。 转换为灰…

cisco防火墙在内网通过外网域名进行访问的配置

1.配置主机的access-list列表 access-list outside_acl extended permit tcp any 192.168.1.123 2.对主机和端口进行映射, 2.1 nat (inside,outside) source static 192.168.1.123 interface service stcp80 stcp8800 注释:先对主机进行外网映射…

React(一)

文章目录 项目地址一、创建第一个react项目二、JSX语法2.1 生成列表2.2 大括号识别JS的表达式2.3 列表循环array2.4 条件判断以及假值显示2.5 复杂条件渲染2.6 事件监听和绑定2.7 使用Fregments返回多个根标签2.8 多条件渲染2.9 导出子组件 三、组件3.1 设置组件3.2 props给子组…

记录一下在原有的接口中增加文件上传☞@RequestPart

首先,咱声明一下: RequestBody和 MultipartFile 不可以 同时使用!!! 因为这两者预期的请求内容类型不同。RequestBody 预期请求的 Content-Type 是 application/json 或 application/xml,而 MultipartFile …

HTTPSOK ---助力阿里云免费 SSL 证书自动续期

目前许多用户面临着 SSL 证书过期续期的难题,尤其是对于阿里云的 免费 SSL 证书,每三个月需要手动申请和更新。为了帮助用户更轻松地管理 SSL 证书,现推出了强大的 HTTPSOK 服务,为用户提供了更便捷的自动续期和管理解决方案。 什…

5G的SUCI、SUPI、5G-GUTI使用场景及关系

使用场景(来源于对23.501、23.502、33.501、23.003的理解) 1、UE初始注册时,根据HN Public Key把SUPI加密成SUCI,并发送初始注册请求 2、AMF转发SUCI给AUSF和UDM进行认证,并获取解密后的SUPI 3、AMF根据SUPI生成一个5G-GUTI,并保…

【微服务】Spring AI 使用详解

目录 一、前言 二、Spring AI 概述 2.1 什么是Spring AI 2.2 Spring AI 特点 2.3 Spring AI 带来的便利 2.4 Spring AI 应用领域 2.4.1 聊天模型 2.4.2 文本到图像模型 2.4.3 音频转文本 2.4.4 嵌入大模型使用 2.4.5 矢量数据库支持 2.4.6 数据工程ETL框架 三、Sp…

【jvm】方法区的理解

目录 1. 说明2. 方法区的演进3. 内部结构4. 作用5.内存管理 1. 说明 1.方法区用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码缓存等数据。它是各个线程共享的内存区域。2.尽管《Java虚拟机规范》中把方法区描述为堆的一个逻辑部分,但它却…

大数据-226 离线数仓 - Flume 优化配置 自定义拦截器 拦截原理 拦截器实现 Java

点一下关注吧!!!非常感谢!!持续更新!!! Java篇开始了! 目前开始更新 MyBatis,一起深入浅出! 目前已经更新到了: Hadoop&#xff0…

编译OpenCV的速度,家里和公司的电脑相差很大

这一段时间,研究OpenCV带ffmpeg的编译问题。然后发现,同样是虚拟机,编译速度,家里的电脑明显比公司慢多了。 都是在SSD上。虚拟机内存,家里是16G,公司是8G。CPU,家里是E5 2667,公司…

Qt 的 QThread:多线程编程的基础

Qt 的 QThread:多线程编程的基础 在现代应用程序中,尤其是需要处理大量数据、进行长时间计算或者进行 I/O 操作时,多线程编程变得至关重要。Qt 提供了一个功能强大且易于使用的线程类 QThread,可以帮助开发者在 Qt 应用程序中实现…

Java 线程池介绍与实践

文章目录 引言概念优势Java 中的线程池实现线程池的核心参数1. corePoolSize:核心线程数2. maximumPoolSize:最大线程数3. keepAliveTime:线程空闲时间4. unit:时间单位5. workQueue:任务队列6. threadFactory&#xf…

富格林:安全指正规防欺诈套路

富格林指出,在现货黄金投资操作中,有众多的投资技巧和投资方式,但其实并不是所有的都适用。投资者应该注意选择安全、可信的投资方式去规防欺诈套路。值得提醒的是,现货黄金虽然拥有很多获利的机会,但也有不少欺诈套路…

PyAEDT:Ansys Electronics Desktop API 简介

在本文中,我将向您介绍 PyAEDT,这是一个 Python 库,旨在增强您对 Ansys Electronics Desktop 或 AEDT 的体验。PyAEDT 通过直接与 AEDT API 交互来简化脚本编写,从而允许在 Ansys 的电磁、热和机械求解器套件之间无缝集成。通过利…

SpringBoot(二十六)SpringBoot自定义注解

注解在springboot日常开发中使用的频率是很高的,官方为我们提供了很多注解,比如:@Autowired、@GetMapping等…… 但是我们有些特定的需求官方提供的注解是没有的。我们可以自定义注解。 下面我们来了解一下自定义注解的过程。 一:元注解 Java为我们提供了几个元注解来自定…

DHTMLX-gantt组件显示不同的颜色

在 dhtmlxGantt 组件中,你可以通过自定义任务的颜色来显示不同的任务类型或状态。这通常通过配置任务的 color 属性来实现。你可以在初始化 Gantt 图表时或在动态添加任务时设置这个属性。 以下是一些常见的方法来为任务设置不同的颜色: 1. 初始化时设…

什么是迭代器?Python迭代器及其用法

迭代器是一种对象,它表示一个数据流,可以一次访问一个成员(元素)。 迭代器从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。 在Python中,迭代器是一个实现了迭代协议的…

什么是C++中的友元函数和友元类?

友元函数(Friend Function)和 友元类(Friend Class)是用于控制类的访问权限的机制。这允许特定的函数或类访问另一个类的私有成员和保护成员,打破了 C 的封装性规则。 友元函数 定义 友元提供了不同类的成员函数之间…