【c#】定义类成员(字段、方法、属性)

本文详细介绍了C#中类的各种成员定义,包括字段、方法和属性等,特别聚焦于访问修饰符、静态成员、自动属性及派生类中的属性重写等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


成员定义

  • public----成员可以由任何代码访问
  • private----成员只能由类中的代码访问(如果没有使用任何关键字,默认使用这个关键字)
  • internal----成员定只能由义他的程序集(命名空间)内部的代码访问
  • protected----成员只能由类或派生类的代码访问
  • protect和internal也可以结合使用   protected internal ,表示它们只能由项目中派生类的代码来访问
  • 用static关键字修饰,则表示它们是类的静态成员,而不是对象的实例成员
1.字段的定义
  • 标准的变量声明格式

class MyClass
{
    public int MyInt;
}

  • readonly 关键字
表示这个字段只能在 执行构造函数的过程中赋值,或者由初始化语句赋值

初始化时赋值
class MyClass
{
    public readonly int MyInt = 2017;
}

  • static 关键字,将字段声明为静态

class MyClass
{
    public static int MyInt;
}

注意:静态字段必须通过定义他们的类来访问,不能通过实例化的对象来访问

上面的示例中,只能这样访问
MyClass.MyInt

  • const 关键字,可以用 const 关键字定义一个常量,其也是静态的,但是不能用 static修饰,否则会出错
2.定义方法
  • 标准函数格式、可访问性和可选的 static 修饰符来声明
注意:用static修饰后,只能通过类访问,不能通过实例化的对象访问

使用关键字
  • virtual----方法可以重写
  • abstract----方法必须在非抽象的派生类中重写(只用于抽象类)
  • override----方法重写了一个基类方法(要重写方法,必须用这个关键字
  • extern----方法定义在其他地方

注意:
如果使用了override,也可以使用 sealed 来指定 派生类中不能对这个方法进一步修改
3.定义属性
  • 属性是一种类的成员,它的实现类似函数访问类似字段
  • 作用是提供一种灵活和安全的机制来访问、修改私有字段
  • 属性必须依赖于字段

  • 属性拥有两个类似于函数的块,set 和 get ,set 设置属性的值,get 获取属性的值
private int myInt; 

public int MyInt
    get{ return myInt * 3;} 
    set{ myInt = value / 3;} 

  • 这两个块称为 访问器,可以用来控制属性的访问级别
  • 可以忽略其中的一个块创建只读或只写属性 (没有set的属性是一种只读属性,没有get的访问器是一种只写属性)
注意:这里的只读和只写只适用于外部代码,类中的其他代码依旧能访问其中的数据
  • get访问器用来返回字段或者计算 并返回字段,它必须以return或者throw终结
  • set访问器类似返回类型为void的函数,使用value的隐式参数
注意:value 关键字表示用户提供的属性值,其类型和属性相同,所以如果属性和字段使用相同的类型,就不用类型转换。

//类中MyClass
private int myInt;

public int MyInt
{
    get{ return myInt;}
    set
    {
        if(value >= 0 && value <=  10) 
            myInt = value;
    }
}

//类外使用
MyClass myObj = new MyClass();

for(int i = -1; i < 1; i++)
{
    myObj.MyInt = i;
}

上述代码中,如果赋给属性的值不满足 value >= 0 || value <=  10,也就是说使用了无效的值,该怎么办?
  1. 什么也不做,如上述代码
  2. 给字段赋默认值
  3. 继续执行,就像没发生错误一样,但是记录下该事件,以备将来分析
  4. 抛出异常
一般情况下,后两种处理方式较好,使用 4 的方法,代码如下

    set
    {
        if (value >= 0 && value <= 10)
        {
            myInt = value;
        }
        else
        {
            throw (new ArgumentOutOfRangeException("MyIntProp", value,
                        "MyIntProp must be assigned a value between 0 and 10"));
        }
    }

  • 属性访问标记可以为public,private,protected,internal,protected internal
  • 因为访问器的访问限制必须比属性的访问限制更加严格,所以
    1. 不能对接口或者显式的接口使用访问修饰符,因为接口里里面所有的默认是public的
    2. 同时具有get,set访问器时,才允许使用访问修饰符,并且只能有一个使用
    3. 如果属性有override修饰的时候,访问器修饰符必须与被重写的匹配
    4. 访问器的可访问级别必须比属性的可访问级别更加严格

private int myInt; 
      public int MyInt  
      { 
          public get { return myInt; } //error  因为访问器的级别和属性相同,所以错误(访问器访问级别更加严格)
          set { myInt = value; } 
      } 

理解:
首先第四条最容易想到,也是很合理的,毕竟是外围的决定内部的。
其次,既然第四条可以理解,那么如果只有一个访问器的时候,访问器访问级别等同属性,如果这个时候再去指 定更加严格的访问级别,那么为何不当初在属性上指定呢?
这条理解了,那么为什么必须同时具有get,set才能添加访问修饰符就更加明确了。

推理:
接口中属性是public的,那么如果接口中只有一个get或者set的时候,我们可以在继承中指明另一个访问器的属性。(接口中只有一个访问器,另一个可以在继承中指明访问级别
但是如果接口中同时具有get,set,那么按照派生和继承的匹配性,这时候就不能这样再指定访问器的访问限制了。 (接口中有两个访问器,不能再指定访问器的访问级别

public interface ISomeInterface 
    int TestProperty 
    { 
        // No access modifier allowed here 
        // because this is an interface. 
        get; 
    } 


public class TestClass : ISomeInterface 
    public int TestProperty 
    { 
        // Cannot use access modifier here because 
        // this is an interface implementation. 
        get { return 10; } 


        // Interface property does not have set accessor, 
        // so access modifier is allowed. 
        protected set { } 
    } 


  • 可以用static 修饰属性,以便随时访问
private static int counter; 
public static int Counter 
    { 
        get { return counter; } 
    } 


  • 属性隐藏

public class Employee 
    private string name; 
    public string Name 
    { 
        get { return name; } 
        set { name = value; } 
    } 

public class Manager : Employee 
    private string name; 


    // Notice the use of the new modifier: 
    public new string Name // use new to hide property in base class 
    { 
        get { return name; } 
        set { name = value + ", Manager"; } 
    } 


  • virtual来修饰属性,派生类使用override来重写属性

public class Parent 
    public virtual int TestProperty 
    { 

        protected set { } 
        get { return 0; } 
    } 
public class Kid : Parent 
    public override int TestProperty 
    { 
        protected set { } 
        get { return 0; } 
    } 


  • abstract 修饰属性,派生类来实现属性

abstract class Shape 
    public abstract double Area 
    { 
        get; 
        set; 
    } 
}

class Square : Shape 
    public double side; 
    public override double Area 
    { 
        get 
        { 
            return side * side; 
        } 
        set 
        { 
            side = System.Math.Sqrt(value); 
        } 
    } 
}   

  • sealed 修饰属性,派生类不能修改属性

  • 接口属性
接口属性不具有函数体


  • 自动属性
当属性访问器中不需要其他访问逻辑时候,就可以使用自动属性,使代码更加简洁

public double TotalPurchases { get; set; } 

有两个使用场景:

在接口中定义,继承接口的类就可以用了。
当有个字段不需要限制访问,为了编程习惯又不想写成公有字段,同时有懒得主动写那个字段名的时候,就使用自动属性吧。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值