C#课程拾遗
近期在学习C#课程,这是系列笔记的第一篇。
参考:https://docs.microsoft.com/zh-cn/dotnet/standard/
"$"在输出字符串中的作用
考虑以下代码:
var names=new List<string> {"liangzi","laisimiao","haha"};
foreach(var name in names)
{
Console.WriteLine($"hello {name}");
Console.WriteLine($"hello {name.ToUpper()}");
}
Console.WriteLine(names.IndexOf("liangzi"));
注意到,在输出的writeline方法盗用的字符串前面有一个$符号,该符号表明:可以在大括号中嵌入Csharp代码,比如文中的name.ToUpper()方法,该方法是将一个英文字母全部转化为大写.以后在写C#时要时刻注意这个方法
某些与课上稍微有冲突而不再使用的类型
List类型
类似于C++中的Vector,C#提供了List类型进行使用,使用方式也是
List<T>
这里不做赘述
From HashTable To Dictionary
如果是用更加一般的泛型,与其采用hashtable不如使用Dictionary< T >类型,该类型被官网认为更加适合使用和执行.
知识点方面的补充
接口 interface
由于C#不允许多继承,因而使用接口来对一些特殊的属性或者方法进行特殊的继承就尤其重要.例如下面的代码:
//定义如下:
interface IEquatable<T>
{
bool Equals(T obj);
}
接口不必去考虑实现(就像抽象类一样)。注意:接口的成员不能是静态成员。
对于上述接口的一个实现如下:
interface IEquable<T>
{
bool equal(T obj);
}
class Point:IEquable<Point>
{
public double x { get; set; }
public double y { get; set; }
public bool equal(Point point)
{
return this.x == point.x && this.y == point.y;
}
}
class Program
{
static void Main(string[] args)
{
var p1 = new Point();
var p2 = new Point();
p1.x = 1;
p1.y = 2;
p2.x = 1;p2.y = 1;
Console.WriteLine($"point1 is equal to point 2? {p1.equal(p2)}");
}
属性 attribute
属性是一种成员,他不是字段!不是对象里面的数据!
属性可用作公共数据成员,但它们实际上是称为访问器的特殊方法。
属性的特点:
比如下面的例子:对于公有属性Hours,既可以通过get方法获取数值,也可以通过set进行是否符合物理意义的检验.
这里的get和set被称为是访问器.
使用表达式主体进行属性的get和set表达
表达式主体是指这种格式:"=>".示例:
//===============================示例1===================================================
using System;
public class Person
{
private string _firstName;
private string _lastName;
public Person(string first, string last) //struct function
{
_firstName = first;
_lastName = last;
}
public string Name => $"{_firstName} {_lastName}";//相当于定义了其set方法.
}
public class Example
{
public static void Main()
{
var person = new Person("Isabelle", "Butts");
Console.WriteLine(person.Name);
}
}
//===============================示例2===================================================
//此处的语法与上面又有所不同,这里需要进行一定的区分
using System;
public class SaleItem
{
string _name;
decimal _cost;
public SaleItem(string name, decimal cost)
{
_name = name;
_cost = cost;
}
public string Name
{
get => _name;
set => _name = value;
}
public decimal Price
{
get => _cost;
set => _cost = value;
}
}
class Program
{
static void Main(string[] args)
{
var item = new SaleItem("Shoes", 19.95m);
Console.WriteLine($"{item.Name}: sells for {item.Price:C2}");
}
}
// The example displays output like the following:
// Shoes: sells for $19.95
根据阅读以上程序,可以看出:本质上,属性是一种方法的集合,该方法使用对象中的私有字段进行输出或者变相显示.
自动实现的属性
这一部分仅供看看.
using System;
public class SaleItem
{
public string Name
{ get; set; }
public decimal Price
{ get; set; }
}
class Program
{
static void Main(string[] args)
{
var item = new SaleItem{ Name = "Shoes", Price = 19.95m };
Console.WriteLine($"{item.Name}: sells for {item.Price:C2}");
}
}
// The example displays output like the following:
// Shoes: sells for $19.95
属性结合了字段和方法的多个方面。
对于对象的用户来说,属性似乎是一个字段,访问属性需要相同的语法。
对于类的实现者来说,属性是一两个代码块,表示 get 访问器和/或 set 访问器。 读取属性时,执行 get 访问器的代码块;向属性赋予新值时,执行 set 访问器的代码块。
将不带 set 访问器的属性视为只读。 将不带 get 访问器的属性视为只写。 将具有以上两个访问器的属性视为读写。
与字段不同,属性不会被归类为变量。 因此,不能将属性作为 ref 或 out 参数传递。
属性具有许多用途:它们可以先验证数据,再允许进行更改;可以在类上透明地公开数据,其中数据实际是从某个其他源(如数据库)检索到的;可以在数据发生更改时采取措施,例如引发事件或更改其他字段的值。
示例:
public class Date
{
private int month = 7; // Backing store
public int Month
{
get
{
return month;
}
set
{
if ((value > 0) && (value < 13))
{
month = value;
}
}
}
}
备注
- 可以将属性标记为 public、private、protected、internal、protected internal 或 private protected。 这些访问修饰符定义该类的用户访问该属性的方式。 相同属性的 get 和 set 访问器可以具有不同的访问修饰符。 例如,get 可能为 public允许从类型外部进行只读访问;而 set 可能为 private 或 protected
- 这一个没看懂:MSDN说可以声明静态的属性,但是我们知道,静态的属性可以在对象没有被创建的时候被引用,我认为这里可能会出现一些额外的问题.
- 可以通过使用 virtual 关键字将属性标记为虚拟属性。 这可使派生类使用 override 关键字重写属性行为。重写虚拟属性的属性也可以是 sealed,指定对于派生类,它不再是虚拟的。 最后,可以将属性声明为 abstract。 这意味着类中没有实现,派生类必须写入自己的实现。