首页 > 编程语言 >学习笔记-《Effective C# 第二版》

学习笔记-《Effective C# 第二版》

时间:2022-11-14 09:24:14浏览次数:38  
标签:name Effective get C# 笔记 int 索引 public 属性

读书笔记

原则1:尽可能地使用属性(property),而不是可直接访问的数据成员

1. 概述

属性一直是C#语言的一等公民。自C# 1.0版本以来,C#对属性进行了一系列的增强,让其表达能力不断提到。你甚至可以为setter和getter指定不同的访问权限。隐式属性也极大降低了声明属性时的工作量,不会比声明数据成员麻烦多少。

属性是一种全功能的、第一等的语言元素,能够以方法调用的形式访问或修改内部数据。成员函数中可以实现的任何功能都可以在属性中实现。

如果你的类里还有Public的变量,如果你还在手写get and set 方法,可以停下来了。

属性允许将数据成员作为共有接口的一部分暴露出去,同时仍旧提供面向对象环境下所需的封装。属性这个语言元素可以让你像访问数据成员一样使用,但其底层依然是用方法来实现的。

.Net Framework假定你使用Property来让外界访问你类里想让外界访问到的数据成员 。实际上也是这样的,因为.Net的数据绑定只支持Property,而不支持公有数据成员的访问。数据绑定的目的就是把一个对象的属性绑定到一个用户界面的control上。数据绑定是通过反射来实现的,如下例:

textBoxCity.DataBindings.Add("Text", address, "City");

这段代码就是把textBoxCity的Text Property绑定到address这个对象的City 属性上。公有的数据成员并不推荐使用,因此Framework Class Library设计器也不支持其实现绑定。这样的设计也保证了我们必须选择合适的面向对象技术。

2. 使用属性,可以方便地加入检查机制

如果你使用了Property,你可以非常轻松的添加一个检查机制,如下面这段代码:

public class CustomerEx
{
private string name;
public string Name
{
get { return name; }
set
{
if (string.IsNullOrEmpty(value))
throw new ArgumentException(
"Name cannot be blank",
"Name");
name = value;
}
//...
}
}

3. 属性可支持多线程

因为属性是用方法实现的,所以它拥有方法所拥有的一切语言特性。

比如,属性增加多线程的支持是非常方便的。你可以加强 get 和 set 访问器 (accessors)的实现来提供数据访问的同步:

public class Customer
{
private object syncHandle = new object();
private string name;
public string Name
{
get
{
lock (syncHandle)
return name;
}
set
{
if (string.IsNullOrEmpty(value))
throw new ArgumentException(
"Name cannot be blank",
"Name");
lock (syncHandle)
name = value;
}
}
// More Elided.
}

4. 属性可以声明为virtual

同样,因为属性是用方法实现的,所以它拥有方法所拥有的一切语言特性,那么同样,属性可以被定义为virtual:

public class Customer
{
public virtual string Name
{
get;
set;
}
}

5. 属性可以声明为接口,以及abstract

显而易见,你也可以把Property扩展为abstract,甚至成为interface的一部分:

public interface INameValuePair
{
object Name
{
get;
}
object Value
{
get;
set;
}
}

6. 属性可以使用泛型

你可以用泛型+接口的属性类型:

public interface INameValuePair<T>
{
T Name
{
get;
}
T Value
{
get;
set;
}
}

7. 给get 与set定义不同的访问权限

如前所述,因为属性是用方法实现的,所以它拥有方法所拥有的一切语言特性。

因为实现Property访问的方法get 与set是独立的两个方法,在C# 2.0之后,你可以给它们定义不同的访问权限,来更好的控制类成员的可见性,如下:

public class Customer
{
private string _name;
public virtual string Name
{
get
{
return _name;
}
protected set
{
_name = value;
}
}
//...
}

8. 在属性中使用索引器

想返回序列中的项,创建一个属性是非常不错的做法,如下例:

public class Customer
{
private int[] _theValues= new int[3] { 1,2,2};

public int this[int index]
{
get
{
return _theValues[index];
}
set
{
_theValues[index] = value;
}
}
}

//usage:
Customer c1 = new Customer();
c1[1] = 666;
var cc1 = c1[1];

索引器和单元素Property有着相同的特性,他们都是作为方法实现的,因此可以在索引器内部实现任意的验证或者计算逻辑。索引器也可为虚的或抽象的,可以声明在接口中,可以为只读或读写。一维且使用数字作为参数的索引器也可以参与数据绑定。使用非整数参数的索引器可以用来定义其他的数据结构,如map和dictionary:

public class AddressEx
{
private Dictionary<int, string> _address = new Dictionary<int, string>();
public string this[int name]
{
get
{
return _address[name];
}
set
{
_address[name] = value;
}
}
}

//usage:
AddressEx a1 = new AddressEx();
a1[1] = "New York";
a1[2] = "Hong Kong";
var a11 = a1[1];

9. 创建多维索引器

为了和多维数组保持一致,我们可以创建多维索引器,在不同的维度上使用相同或不同类型:

class ComputeValueClass
{
public int this[int x, int y]
{
get { return ComputeValue(x, y); }
}

public int this[int x, string name]
{
get { return ComputeValue(x, name); }
}

private int ComputeValue(int x, int y)
{
//...
}

private int ComputeValue(int x, string y)
{
//...
}

}

值得注意的是所有索引器必须使用 this 关键字声明。在 C# 中你不能自己命名索引器。所以一个类型的索引器必须有不同的参数列表来避免歧义。几乎所有的属性的功能都适用索引器。索引器可以是 virtual 或 abstract ;索引器的 setters 和 getters 可以不同的访问限制。不过,你不能像创建隐式属性一样创建隐式索引器。

10. 总结

总而言之,无论什么时候,当你想让你类内部的数据被外界访问到时(无论是public还是protected),一定要用属性。对于序列和字典,可以使用索引器。

使用Property,你可以得到如下好处:

1.数据绑定的支持

2.对于需求变化有更强的适应性,更方便的修改实现方法。

记住,现在多花1分钟使用Property,会在你修改程序以适应设计变化时,为你节约n小时。

 

 

点击关注,共同学习!
[安全狗的自我修养](https://mp.weixin.qq.com/s/E6Kp0fd7_I3VY5dOGtlD4w)


[github haidragon](https://github.com/haidragon)


https://github.com/haidragon

标签:name,Effective,get,C#,笔记,int,索引,public,属性
From: https://www.cnblogs.com/haidragon/p/16887989.html

相关文章

  • 学习笔记-《GPU 编程与CG 语言之阳春白雪下里巴人》
    第一章绪论1.1ProgrammableGraphicsProcessingUnit发展历程ProgrammableGraphicsProcessingUnit(GPU),即可编程图形处理单元,通常也称之为可编程图形硬件。GP......
  • 神币概率期望讲课笔记
    一些结论\(n\)个点的有向图从\(1\)走到\(n\)期望时间柿子就是这样子\[f_x=1+\frac{\sumf_v}{in_x}\]“每一刻事件有\(p\)概率发生,问事件发生期望时间”列出......
  • MES工单工艺线路条码系统NetMVC源码
    概述    系统操作分为两部分:一、生产主管:进入系统设置工单、设置产品扫描工站、设置每个工站扫描的物料条码、维护物料表。二、产线工人:扫描条码。......
  • Ubuntu: How to create a new file? This command you need to know: touch
    howtocreateanewfileinlinuxUbuntu.touchtouch1.txt2.txtandthenyoucangetthenewfileincurrentdirectory.>>1.txtecho'txtcontent.'>......
  • k8s删除Terminating状态的namespace
    使用参数:--forcegrace-period=0强制删除无效!解决办法就是将资源内的finalizers字段删除。  #定义变量NAMESPACE=test#proxy后台监听8001kubectlproxy&#jq将......
  • 【2022.11.14】pytorch的使用相关(二)
    【2022.11.04】pytorch的初始化前言参考代码来自于:Fafa-DL/Lhy_Machine_Learning:李宏毅2021春季机器学习课程课件及作业(github.com)数据集来自于:https://github.com......
  • Nacos 版本不一致报错: Request nacos server failed
    在做微服务开发中,测试环境使用Nacos没有问题,但是生产环境服务启动一直报错:com.alibaba.nacos.api.exception.NacosException:Requestnacosserverfailed: atcom.ali......
  • ASP.NET Core教程-Configuration(配置)-配置运行环境
    更新记录转载请注明出处:2022年11月14日发布。2022年11月12日从笔记迁移到博客。配置运行环境在程序启动时,会读取ASPNETCORE_ENVIRONMENT环境变量的值。如果它的......
  • C++ explicit关键字详解
    C++编码时,可以通过构造函数将相应的数据类型转换成为C++类的对象,从某种程度来说给编码带来了方便,但并不是每次都正确,为了避免这种情况,C++提供了explicit关键字,相对于implic......
  • 如何设置JavaScript的版本为6
    如何设置JavaScript的版本为6设置里面搜索JavaScript,语言和框架——>JavaScript 使用JavaScript6的好处例如:for循环中可以使用let而不用var//这里出现let是因为Jav......