类中static、const、readonly、partial修饰符

static

修饰类成员:
static在C#中的用法与C++类似,当声明一个类成员为静态时,意味着无论有多少个类的对象被创建,只会有一个静态成员的副本,static变量可在成员函数或类的定义外部进行初始化,也可以在类内部定义初始化静态变量,被static修饰的函数也称静态函数,静态函数成员可以访问其他静态成员,但不能访问实例成员,我们可以从类的外部访问静态成员,但在访问时,C#和C++在访问时有所不同C#中class.静态成员,且C#中只能用类来访问static成员,而不能用对象.静态成员来访问C++中:既可以使用class::静态成员 来访问,也可以通过对象.静态成员来访问,只是C++中在类内部定义完static成员后必须在类外进行初始化

    class Program
    {
        static int i = 100;
        static void Main(string[] args)
        {
            Console.WriteLine(Program.i); //100
        }
    }

修饰类(静态类):

静态类中所有成员都是静态的,静态类用于存放不受实例数据影响的数据和函数,静态类的一个常见的用途可能就是创建一个包含一组数学方法和值的数学库,关于静态类的特点如下:
(1)类本身必须标记为static  例如:static public class A
(2)类的所有成员必须是静态的
(3)类可以有一个静态构造函数,但不能有实例构造函数,不能创建该类的实例
(4)静态类是隐式密封的,也就是说不能继承静态类

    static class A
    {
        static public int a = 100;
        static public void foo() { }  //成员必须是静态的
        //public void foo() { } 不能有实例成员
    }
    //class B : A { }  不能继承静态类
    class Program
    {
        static void Main(string[] args)
        {
            //A a = new A(); 不能创建静态类的实例
            Console.WriteLine(A.a);
        }
    }

const

const在C#中的使用与C++有所不同,const用于在类中定义成员常量,它只能修饰值类型数据,不能修饰引用类型数据,与本地常量类似,用于初始化成员常量的值在编译时必须是可计算的,而且C#在声明成员常量的时候就必须对其进行初始化,否则会出错,C++中const修饰的数据成员则既可以在声明时直接初始化,也可以在声明后在构造函数的初始化列表中进行初始化定义,与C++不同,C#中没有全局常量,每个常量都必须声明在类内。

特点:常量的表现像静态值,它们对类的每个实例都是"可见的",而且即使没有类的实例也可以使用,所以也可以通过
class.成员常量来访问,与真正的静态量不同,常量没有自己的存储位置,而是在编译时被编译器替换,这种方式类似于C++中的#define值。虽然常量成员表现的像一个静态量,但不能将常量声明为static,C++中static和const是可以一起使用的

    class Program
    {
        const int i = 10;
        //const int i; 错误,成员常量必须在定义的时候就初始化且不允许再次赋值
        //const static int=100; 不存在这种写法
        static void Main(string[] args)
        {
            Console.WriteLine(Program.i); //10
        }
    }

readonly

字段可以用readonly修饰符来声明,其作用类似于将字段声明为const,一但值被设定就不能改变,readonly既可以修饰值类型数据也可以修饰引用类型数据,readonly修饰值类型数据只能直接初始化或者在构造函数中初始化,如果尝试在其他方法(即使这个方法只被构造函数调用)中初始化,会得到一个编译错误

readonly修饰值类型数据与引用类型数据的不同:

1.修饰值类型:readonly修饰的值类型数据不能在任何地方对这个值进行修改,作用相当于const
2.修饰引用类型:readonly修饰的引用类型数据不能在任何地方对这个引用(理解为指针更好)进行修改,但是可以修改它指向的数据内容

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace GameMain
{
    class Program
    {
        private const int a = 100;
        static void Main(string[] args)
        {
            dd d = new dd();
            //可以改变readonly修饰的引用类型数据所指向的值
            d.fun();
            d.dic.Add(2, 1);
            foreach (var v in d.dic)
            {
                Console.WriteLine(v.Key);
                Console.WriteLine(v.Value);
                //打印 1 1 2 1
            }
            //d.i = 1;  不能改变readonly修饰的值类型数据的值
        }
    }

    public class dd
    {
        public readonly Dictionary<int, int> dic = new Dictionary<int, int>();
        public readonly int i = 100;
        
        public void fun()
        {
            dic.Add(1, 1);
        }
    }
}

readonly与const的区别:
(1)const字段只能在字段的声明语句中初始化,而readonly字段没有这个限制
(2)const字段的值必须在编译时决定,而readonly字段的值,可以在运行时决定,这种增加的自由性允许你在不同的环境或不同的构造函数中设置不同的值
(3)和const不同,const行为总是静态的,而对于readonly字段,它可以是实例字段也可以是静态字段,它在内存中有存储位置

    class Program
    {
        public readonly int a;
        public static readonly int b;
    
        static Program()
        {
            b = 200; //static修饰的可在静态构造函数中初始化
        }

        Program()
        {
            a = 100; 
        }

        static void Main(string[] args)
        {
            Program p = new Program();
            Console.WriteLine(p.a);  //100
            Console.WriteLine(Program.b);  //200
        }
    }

partial

partial为分部类型,在C#中类的声明可以分割成几个分部类的声明。类型修饰符partial不是关键字,所以在其他上下文中,可以在程序中把它用作标识符,但直接用在关键字class、struct或interface之前时,它表示分部类型。

partial声明分部类:
(1)每个分部类的声明都含有一些类成员的声明
(2)类的分部类声明可以在同一文件中也可以在不同文件中
(3)每个局部声明必须被标为partial class,而不是单独的关键字class
(4)组成类的所有分部类声明必须在一起编译,使用分部声明的类必须有相同的含义,就好像所有类成员都声明在一个单独的类声明体内

分部方法时声明在分部类中不同部分的方法,分部方法的不同部分可以声明在不同的分部类中

partial声明分部方法:
(1)定义声明和实现声明的签名和返回类型必须匹配
(2)返回类型必须是void
(3)签名不能包括访问修饰符,这使分部方法时隐式私有的
(4)参数列表不能包含out参数
(5)在定义声明和实现声明中都必须包含上下文关键字partial,直接放在关键字void之前
(6)可以有定义部分而没有实现部分,在这种情况下编译器把方法的声明以及方法内部任何对方法的调用都移除,不能只有分部方法的实现部分而没有定义部分

    partial class A
    {
        partial void foo(int i);  //声明
    }

    partial class A
    {
        partial void foo(int i)  //实现
        {
            Console.WriteLine(i);  //1000
        }
        public void fun(int i)
        {
            foo(i);   
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            A a = new A();
            //a.foo();  分部方法是private的权限,所以不能直接访问
            a.fun(1000);  //如果想调用分部方法,只能再定义一个接口
        }
    }

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值