以前是学C++的,初次学微软的C#头都大了。什么字段,常量,属性,方法......微软把别人的东西拿来糅合在C#里,弄成了一个“大杂烩”。其实,说到底,“字段”不就是“变量”吗,所谓的“方法”不就是“函数”吗,故弄玄虚!从MSDN上弄来了详细的介绍,看下面:

字段:

“字段”是直接在结构中声明的任何类型的变量。 字段是其包含类型的“成员”。

类或结构可以拥有实例字段或静态字段,或同时拥有两者。 实例字段特定于类型的实例。 如果您拥有类 T 和实例字段 F,可以创建类型 T 的两个对象,并修改每个对象中 F 的值,这不影响另一对象中的该值。 相比之下,静态字段属于类本身,在该类的所有实例中共享。 从实例 A 所做的更改将立刻呈现在实例 B 和 C 上(如果它们访问该字段)。

通常应仅为具有私有或受保护可访问性的变量使用字段。 您的类向客户端代码公开的数据应通过方法属性索引器提供。 通过使用这些构造间接访问内部字段,可以针对无效的输入值提供防护。 存储由公共属性公开的数据的私有字段称为“后备存储”或“支持字段”。

字段通常存储这样的数据:该数据必须可供多个类方法访问,并且其存储期必须长于任何单个方法的生存期。 例如,表示日历日期的类可能有三个整数字段:一个表示月份,一个表示日期,还有一个表示年份。 不在单个方法范围外部使用的变量应在方法体自身范围内声明为局部变量。

在类块中通过指定字段的访问级别,然后指定字段的类型,再指定字段的名称来声明这些字段。 例如:

 1 public class CalendarEntry
2 {
3 // private field
4 private DateTime date;
5
6 // public field (Generally not recommended.)
7 public string day;
8
9 // Public property exposes date field safely.
10 public DateTime Date
11 {
12 get
13 {
14 return date;
15 }
16 set
17 {
18 // Set some reasonable boundaries for likely birth dates.
19 if (value.Year > 1900 && value.Year <= DateTime.Today.Year)
20 {
21 date = value;
22 }
23 else
24 throw new ArgumentOutOfRangeException();
25 }
26
27 }
28
29 // Public method also exposes date field safely.
30 // Example call: birthday.SetDate("1975, 6, 30");
31 public void SetDate(string dateString)
32 {
33 DateTime dt = Convert.ToDateTime(dateString);
34
35 // Set some reasonable boundaries for likely birth dates.
36 if (dt.Year > 1900 && dt.Year <= DateTime.Today.Year)
37 {
38 date = dt;
39 }
40 else
41 throw new ArgumentOutOfRangeException();
42 }
43
44 public TimeSpan GetTimeSpan(string dateString)
45 {
46 DateTime dt = Convert.ToDateTime(dateString);
47
48 if (dt != null && dt.Ticks < date.Ticks)
49 {
50 return date - dt;
51 }
52 else
53 throw new ArgumentOutOfRangeException();
54
55 }
56 }

若要访问对象中的字段,请在对象名称后面添加一个句点,然后添加该字段的名称,比如 objectname.fieldname。 例如:

1 CalendarEntry birthday = new CalendarEntry();
2 birthday.day = "Saturday";

声明字段时可以使用赋值运算符为字段指定一个初始值。 例如,若要自动将 "Monday" 赋给 day 字段,需要声明 day,如下例所示:

public class CalendarDateWithInitialization
{
public string day = "Monday";
//...
}

字段的初始化紧靠调用对象实例的构造函数之前。 如果构造函数为字段赋值,则该值将覆盖字段声明期间给出的任何值。

字段可标记为 publicprivateprotectedinternal 或 protected internal。 这些访问修饰符定义类的使用者访问字段的方式。 有关更多信息,请参见 访问修饰符(C# 编程指南)

可以选择将字段声明为 static。 这使得调用方在任何时候都能使用字段,即使类没有任何实例。 有关更多信息,请参见 静态类和静态类成员(C# 编程指南)

可以将字段声明为 readonly。 只读字段只能在初始化期间或在构造函数中赋值。 static readonly 字段非常类似于常数,只不过 C# 编译器不能在编译时访问静态只读字段的值,而只能在运行时访问。 有关更多信息,请参见 常量(C# 编程指南)

常量:

常量是在编译时已知并在程序的生存期内不发生更改的不可变值。 常量使用 const 修饰符进行声明。 只有 C# 内置类型(System.Object 除外)可以声明为 const。 有关内置类型的列表,请参见内置类型表(C# 参考)。 用户定义的类型(包括类、结构和数组)不能为 const。 请使用 readonly 修饰符创建在运行时初始化一次即不可再更改的类、结构或数组。

C# 不支持 const 方法、属性或事件。

可以使用枚举类型为整数内置类型(例如 int、uint、long 等等)定义命名常量。 有关更多信息,请参见 enum(C# 参考)

常量必须在声明时初始化。 例如:

1 class Calendar1
2 {
3 public const int months = 12;
4 }

在此示例中,常量 months 始终为 12,不可更改,即使是该类自身也不能更改它。 实际上,当编译器遇到 C# 源代码(例如 months)中的常量修饰符时,将直接把文本值替换到它生成的中间语言 (IL) 代码中。 因为在运行时没有与常量关联的变量地址,所以 const 字段不能通过引用传递,并且不能在表达式中作为左值出现。

可以同时声明多个相同类型的常量,例如:

class Calendar2
{
const int months = 12, weeks = 52, days = 365;
}

如果不会造成循环引用,用于初始化一个常量的表达式可以引用另一个常量。 例如:

1 class Calendar3
2 {
3 const int months = 12;
4 const int weeks = 52;
5 const int days = 365;
6
7 const double daysPerWeek = (double) days / (double) weeks;
8 const double daysPerMonth = (double) days / (double) months;
9 }

常量可标记为 publicprivateprotectedinternal 或 protectedinternal。 这些访问修饰符定义类的用户访问该常量的方式。 有关更多信息,请参见 访问修饰符(C# 编程指南)

因为常量值对该类型的所有实例是相同的,所以常量被当作 static 字段一样访问。 不使用 static 关键字声明常量。 未包含在定义常量的类中的表达式必须使用类名、一个句点和常量名来访问该常量。 例如:

int birthstones = Calendar.months;

属性:

属性是这样的成员:它提供灵活的机制来读取、编写或计算某个私有字段的值。 可以像使用公共数据成员一样使用属性,但实际上它们是称作“访问器”的特殊方法。 这使得可以轻松访问数据,此外还有助于提高方法的安全性和灵活性。

在本示例中,TimePeriod 类存储一个时间段。 在内部,类以秒为单位存储时间,但客户端使用名为 Hours 的属性能够以小时为单位指定时间。 Hours 属性的访问器执行小时和秒之间的转换。

 1 class TimePeriod
2 {
3 private double seconds;
4
5 public double Hours
6 {
7 get { return seconds / 3600; }
8 set { seconds = value * 3600; }
9 }
10 }
11
12
13 class Program
14 {
15 static void Main()
16 {
17 TimePeriod t = new TimePeriod();
18
19 // Assigning the Hours property causes the 'set' accessor to be called.
20 t.Hours = 24;
21
22 // Evaluating the Hours property causes the 'get' accessor to be called.
23 System.Console.WriteLine("Time in hours: " + t.Hours);
24 }
25 }
26 // Output: Time in hours: 24
  • 属性使类能够以一种公开的方法获取和设置值,同时隐藏实现或验证代码。

  • get 属性访问器用于返回属性值,而 set 访问器用于分配新值。 这些访问器可以有不同的访问级别。 有关更多信息,请参见 限制访问器可访问性(C# 编程指南)

  • value 关键字用于定义由 set 取值函数分配的值。

  • 不实现 set 取值函数的属性是只读的。

  • 对于不需要任何自定义访问器代码的简单属性,可考虑选择使用自动实现的属性。 有关更多信息,请参见自动实现的属性(C# 编程指南)

方法:

“方法”是包含一系列语句的代码块。 程序通过“调用”方法并指定所需的任何方法参数来执行语句。 在 C# 中,每个执行指令都是在方法的上下文中执行的。 Main 方法是每个 C# 应用程序的入口点,在启动程序时由公共语言运行时 (CLR) 调用。

通过指定方法的访问级别(例如 public 或 private)、可选修饰符(例如 abstract 或 sealed)、返回值、名称和任何方法参数,可以在结构中声明方法。 这些部分统称为方法的“签名”。

方法参数括在括号中,并用逗号隔开。 空括号表示方法不需要参数。 下面的类包含三个方法:

 1 abstract class Motorcycle
2 {
3 // Anyone can call this.
4 public void StartEngine() {/* Method statements here */ }
5
6 // Only derived classes can call this.
7 protected void AddGas(int gallons) { /* Method statements here */ }
8
9 // Derived classes can override the base class implementation.
10 public virtual int Drive(int miles, int speed) { /* Method statements here */ return 1; }
11
12 // Derived classes must implement this.
13 public abstract double GetTopSpeed();
14 }

在对象上调用方法类似于访问字段。 在对象名称之后,依次添加句点、方法名称和括号。 参数在括号内列出,并用逗号隔开。 因此,可以按以下示例中的方式调用 Motorcycle类的方法:

 1 class TestMotorcycle : Motorcycle
2 {
3
4 public override double GetTopSpeed()
5 {
6 return 108.4;
7 }
8
9 static void Main()
10 {
11
12 TestMotorcycle moto = new TestMotorcycle();
13
14 moto.StartEngine();
15 moto.AddGas(15);
16 moto.Drive(5, 20);
17 double speed = moto.GetTopSpeed();
18 Console.WriteLine("My top speed is {0}", speed);
19 }
20 }

方法定义指定所需任何“形参”的名称和类型。 调用代码在调用方法时,将为每个形参提供称为“实参”的具体值。 实参必须与形参类型兼容,但调用代码中使用的实参名称(如果有)不必与方法中定义的形参名称相同。 例如:

 1 public void Caller()
2 {
3 int numA = 4;
4 // Call with an int variable.
5 int productA = Square(numA);
6
7 int numB = 32;
8 // Call with another int variable.
9 int productB = Square(numB);
10
11 // Call with an integer literal.
12 int productC = Square(12);
13
14 // Call with an expression that evaulates to int.
15 productC = Square(productA * 3);
16 }
17
18 int Square(int i)
19 {
20 // Store input argument in a local variable.
21 int input = i;
22 return input * input;
23 }

默认情况下,将值类型传递给方法时,传递的是副本而不是对象本身。 因此,对参数所做的更改对于调用方法中的原始副本没有影响。 可以使用 ref 关键字通过引用传递值类型。 有关更多信息,请参见传递值类型参数(C# 编程指南)。 有关内置值类型的列表,请参见值类型表(C# 参考)

当引用类型的对象传递给方法时,对对象的引用传递。 即方法接收不是对象,还指示对象的位置的参数。 如果更改对象的成员通过使用该引用,更改反映在被调用的方法的参数,因此,即使通过对象的值。

如下面的示例所示,通过使用 class 关键字,则创建一个引用类型。

public class SampleRefType
{
public int value;
}

现在,因此,如果您通过根据方法的此类型的对象,对对象的引用传递。 下面的示例通过类型 SampleRefType 对象传递给方法 ModifyObject。

 1 public static void TestRefType()
2 {
3 SampleRefType rt = new SampleRefType();
4 rt.value = 44;
5 ModifyObject(rt);
6 Console.WriteLine(rt.value);
7 }
8 static void ModifyObject(SampleRefType obj)
9 {
10 obj.value = 33;
11 }

该示例实质上执行操作与前例同样因为它通过值传递实参传递给方法。 但,使用引用类型,则结果是不同的。 在对该参数进行 value 字段的 ModifyObject 做的修改,obj,也会更改参数,rt的 value 字段,在 TestRefType 方法。 TestRefType 方法显示 33 作为输出。

方法可以向调用方返回值。 如果返回类型(方法名称前列出的类型)不是 void,则方法可以使用 return 关键字来返回值。 如果语句中 return 关键字的后面是与返回类型匹配的值,则该语句将该值返回给方法调用方。 return 关键字还会停止方法的执行。 如果返回类型为 void,则可使用没有值的 return 语句来停止方法的执行。 如果没有return 关键字,方法执行到代码块末尾时即会停止。 具有非 void 返回类型的方法才能使用 return 关键字返回值。 例如,下面的两个方法使用 return 关键字来返回整数:

 1 class SimpleMath
2 {
3 public int AddTwoNumbers(int number1, int number2)
4 {
5 return number1 + number2;
6 }
7
8 public int SquareANumber(int number)
9 {
10 return number * number;
11 }
12 }

C# 方法,属性,字段的更多相关文章

  1. python-->基础-->005-->类的三大成员:方法+属性+字段

    ---恢复内容开始--- 一.方法 python的方法中分为三种方法: 静态方法 动态方法(普通方法) 类方法 其中常用的方法为:静态方法和动态方法 class MyClass: def __init ...

  2. python_way,day8 面向对象【多态、成员--字段 方法 属性、成员修饰符、特殊成员、异常处理、设计模式之单例模式、模块:isinstance、issubclass】

    python_way day8 一.面向对象三大特性: 多态 二.面向对象中的成员 字段.方法属性 三.成员修饰符 四.特殊成员 __init__.__doc__.__call__.__setitem ...

  3. Ninject依赖注入——构造函数、属性、方法和字段的注入

    Ninject依赖注入——构造函数.属性.方法和字段的注入(三) 1.Ninject简介 Ninject是基于.Net平台的依赖注入框架,它能够将应用程序分离成一个个高内聚.低耦合(loosely-c ...

  4. [一]class 文件浅析 .class文件格式详解 字段方法属性常量池字段 class文件属性表 数据类型 数据结构

    前言概述  本文旨在讲解class文件的整体结构信息,阅读本文后应该可以完整的了解class文件的格式以及各个部分的逻辑组成含义   class文件包含了java虚拟机指令集 和  符号表   以及若 ...

  5. Python类总结-字段,方法,属性区别及StaticMethod, Property,私有字段和私有属性

    类包含下列 静态属性 动态属性 静态方法 动态方法 class Province: #静态字段--属于类,调用方法类.字段名 memo = "中国23个省之一" #动态字段--属于 ...

  6. c# 类成员的定义 定义方法、字段和属性【转】

    c# 类成员的定义 定义方法.字段和属性c#类的成员包括字段.属性和方法.所有成员都有自己的访问级别,用下面的关键字之一来定义:public----成员可以有任何代码访问:private----成员只 ...

  7. IntelliJ IDEA快速创建属性字段的get和set方法

    1.写好属性字段后,在代码面板右击,选择generator… ​ 再选择 Getter and Setter ​ 全选中(Ctrl + A),点击OK! ​ 2.也可以选择使用快捷键:alt+inse ...

  8. [源码]Literacy 快速反射读写对象属性,字段

    Literacy 说明 Literacy使用IL指令生成方法委托,性能方面,在调用次数达到一定量的时候比反射高很多 当然,用IL指令生成一个方法也是有时间消耗的,所以在只使用一次或少数几次的情况,不但 ...

  9. 玩转动态编译 - 高级篇:二,IL设置静态属性,字段和类型转换

    静态属性赋值 先来看 Reflector反射出的IL源码(感谢Moen的提示),这次用 Release模式编译,去掉那些无用的辅助指令 public void AAA(string s) { MyCl ...

  10. geotrellis使用(十一)实现空间数据库栅格化以及根据属性字段进行赋值

    Geotrellis系列文章链接地址http://www.cnblogs.com/shoufengwei/p/5619419.html 目录 前言 安装空间数据库 空间数据库栅格化 根据属性字段进行赋 ...

随机推荐

  1. python3 类的属性、方法、封装、继承及小实例

    Python 类 Python中的类提供了面向对象编程的所有基本功能:类的继承机制允许多个基类,派生类可以覆盖基类中的任何方法,方法中可以调用基类中的同名方法. 对象可以包含任意数量和类型的数据. p ...

  2. Docker 的安装与使用

    账号:xcj26密码:X*c*j*5**6**邮箱:**j26@126.com   账号:xichji密码:X*c*j*5**6**邮箱:45*666***@qq.com   摘自:https://b ...

  3. Zookeeper基础命令操作

    转载链接:https://blog.csdn.net/dandandeshangni/article/details/80558383 安装参考链接https://blog.csdn.net/qiun ...

  4. JS 类和继承

    function User(name, pass) { this.name = name this.pass = pass } User.prototype.showName = function ( ...

  5. Ruby的异常处理

    Ruby在处理0.1+0.2是会出现精度问题: 许多语言都有类似问题,详见网址:http://0.30000000000000004.com/ Ruby的异常处理 如果异常处理范围是整个方法体,可以省 ...

  6. UIButton设置按钮点击范围大于可视范围

    自定义按钮类型CustomButton,继承UIButton,重写pointInside函数改变点击响应范围. 例如,按钮点击范围比实际高度上下增加6. CustomButton.h @interfa ...

  7. Docker环境安装部署Java应用(含安装Tomcat和JDK)

    1.部署思路 两台docker机(centos 7系统),Docker 版本:18.09.6, build 481bc77156 Docker host IP:192.168.102.135 Dock ...

  8. 解决Prism中Region的GetView不起作用问题

    通常情况下在Region中添加View时我们需要先判断View是否在Region中已存在,但如果我们在Region.Add的方法调用不当时,我们在GetView中始终返回Null,原因自然是Add时出 ...

  9. Libvirt Live Migration 与 Pre-Copy 实现原理

    目录 文章目录 目录 Libvirt 的 Live Migration 网络数据传输层 控制层 通过 libvirt 库实现虚拟机迁移的示例 KVM 的预拷贝(Pre-Copy)Live Migrat ...

  10. Dart学习笔记-循环

    1.for循环 main() { // for循环 ; i < ; i++) { print(i); // 0,1,2,3,4,5,6,7,8,9 } } 2.while循环 main() { ...