C#基础-----索引器,静态类,值类型和引用类型

本文详细介绍了C#编程中的索引器、访问修饰符和静态类的概念与应用,包括如何使用索引器简化访问类成员、访问修饰符的五种作用及约束、静态类的特性及其使用场景。并通过代码示例深入探讨了静态成员与实例成员的区别,值类型与引用类型的传递方式,以及它们在内存上的存储差异。

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

1索引器

索引器的目的就是为了方便而已,可以再该类型的对象后面直接加一对[]就能访问该类型中的成员内容了

class Program
    {
        static void Main(string[] args)
        { 
            ////索引器的目的就是为了方便而已,可以在该类型的对象后面直接加一对中括号[]就能访问该类型中的成员内容了
            Person p = new Person();
            p[0] = 19;
            Console.WriteLine(p[0]);
            p[1] = "张三";
            Console.WriteLine(p[1]);

            p[2] = "zhangsan@yahoo.com";
            Console.WriteLine(p[2]);

            Console.WriteLine(p["age"]);
            Console.ReadKey();

            MyClass mc = new MyClass();
            //mc._cars[0];
            // mc[0]
            for (int i = 0; i < mc.Length; i++)
            {
                Console.WriteLine(mc[i]);
            }
            //Console.ReadKey();

            ItcastClass ic = new ItcastClass();
            ic[0] = "aaaa";
            for (int i = 0; i < ic.NameLength; i++)
            {
                Console.WriteLine(ic[i]);
            }
            Console.ReadKey();
        }
    }

    public class MyClass
    {
        private string[] _cars = new string[] { "奔驰", "宝马", "法拉利", "福特", "布加迪威龙" };

        public int Length
        {
            get
            {
                return _cars.Length;
            }
        }

        //索引器最终编译的的时候会生成一个名字叫Item的属性
        public string this[int index]
        {
            get
            {
                return _cars[index];
            }
            set
            {
                _cars[index] = value;
            }
        }

        //public string Item
        //{
        //    get;
        //    set;
        //}

    }


    public class Person
    {


        //增加一个索引器, 索引器的语法格式与类的属性的语法格式很像、

        private int _age;

        public object this[int index]
        {
            get
            {
                switch (index)
                {
                    case 0:
                        return _age;
                    case 1:
                        return _name;
                    default:
                        return _email;
                }
            }
            set
            {
                switch (index)
                {
                    case 0:
                        this._age = Convert.ToInt32(value);
                        break;
                    case 1:
                        this._name = (value == null) ? null : value.ToString();
                        break;
                    default:
                        this._email = (value == null) ? null : value.ToString();
                        break;
                }
            }
        }

        public object this[string key]
        {
            get
            {
                switch (key)
                {
                    case "age":
                        return _age;
                    case "name":
                        return _name;
                    default:
                        return _email;
                }
            }
            set
            {
                switch (key)
                {
                    case "age":
                        this._age = Convert.ToInt32(value);
                        break;
                    case "name":
                        this._name = value == null ? null : value.ToString();
                        break;
                    default:
                        this._email = value == null ? null : value.ToString();
                        break;
                }
            }
        }
        private string _name;
        private string _email;
    }

2,访问修饰符

作用:指明程序的其他部分如何访问该成员。共5种

private 当前类中可以访问,类中成员的默认访问修饰符

protected  当前类和子类可以访问(在继承中用)

internal  当前程序集内部可以访问,类如果不加访问修饰符,则默认为internal

protected internal 当前程序集或子类中(不同程序集也可以访问)

public 任何地方

访问级别约束

1)子类的访问级别不能比父类高(会暴漏父类的成员)

2)类中属性或字段的访问级别不能比所对应的类型访问级别高

3)方法的访问级别不能比方法的参数和返回值的访问级别高


3,静态类和静态成员

静态成员是与“类”相关,而非“实例相关”。

普通类中的静态成员static:只能通过类名访问,静态方法中只能访问静态成员,或通过对象访问实例成员,多个对象共享同一个静态成员

静态类:一般都用作工具类,里面都是一些工具函数,静态类中只包含静态成员,静态构造函数不能有参数,不能有访问修饰符(默认private)静态构造函数在第一次使用该静态类的时候只执行一次。

 静态成员属于类所有,非静态成员属于类的实例所有

C#静态方法属于所有类,类实例化前即可使用。在实例方法中可以直接调用静态方法,在静态方法中不能直接调用实例方法。

静态方法和静态变量创建后始终使用同一内存块(静态存储区),而实例的方法会创建多个内存。

静态类和静态成员在程序中的任何一个地方都可以访问,不会因为超出了方法的作用域而不能访问,所以静态类和静态成员只有在程序退出的时候才会释放资源

静态类不能被实例化,就不会由对象,而this表示的是当前对象,所以静态类中不能使用this

静态和非静态的区1)、在非静态类中,既可以有实例成员,也可以有静态成员。2)、在调用实例成员的时候,需要使用对象名.实例成员;
在调用静态成员的时候,需要使用类名.静态成员名;
总结:静态成员必须使用类名去调用,而实例成员使用对象名调用。 静态函数中,只能访问静态成员,不允许访问实例成员。 实例函数中,既可以使用静态成员,也可以使用实例成员。静态类中只允许有静态成员,不允许出现实例成员。

什么时候用静态类:
    1>在整个应用程序中要共享某些数据的时候可以使用静态类。
    2>静态类不能创建对象,使用的时候直接通过类名来操作成员,(使用方便),所以说对于那些类中包含有大量的方法,并且类不需要创建对象的时候,可以使用静态类。


静态非静态
static关键字不需要static关键字
使用类名调用使用实例对象调用
在静态方法中可以访问静态成员在实例方法中,可以直接访问静态成员
在静态方法中不可以直接访问实例成员在实例方法中可以直接访问实例成员
调用前初始化实例化对象时初始化


4,值类型和引用类型

值类型:int    char    double   floatlongshortbyteboolenumstructdecimal

值类型都是隐式继承自ValueType,值类型不能继承,只能实现接口,存放在栈中。

引用类型:string数组接口委托 

引用类型都派生自System.Object,引用类型可以继承。 存放在堆中。

ref把值类型改为引用类型

区别:
1、值类型和引用类型在内存上存储的地方不一样。
2、在传递值类型和传递引用类型的时候,传递的方式不一样。


结构中不能有显示无参构造函数(隐式),结构中不能给字段赋初始值

值类型和引用类型作为参数    引用传递

class Program
    {
        static void Main(string[] args)
        {

            #region 值类型与引用类型介绍

            //// 值类型, 栈
            ////int  short byte char bool double float struct enum decimal 


            ////引用类型 string 数组 类 接口 委托 
            ////堆
            //string s = "a";
            //s = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";

            ////值类型
            //int n = 100;

            //int m = n;

            //m = m + 1;

            //Console.WriteLine(n);
            //Console.ReadLine();


            ////引用类型
            //Person p = new Person();
            //p.Age = 100;

            //Person p1 = p;

            //p1.Age = 120;

            //Console.WriteLine(p.Age);
            //Console.ReadKey();

            #endregion


            int n = 10;
            M1(ref n);
            Console.WriteLine(n);//11
            //Console.ReadKey();

            Person p = new Person();
            p.Age = 100;

            M2(ref p);

            Console.WriteLine(p.Age);//101

            Person p1 = new Person();
            p1.Age = 100;
            M3(ref p1);
            Console.WriteLine(p1.Age);//200

            Person p2 = new Person();
            p2.Age = 100;
            M4(ref p2);
            Console.WriteLine(p2.Age);//1

            string name = "科比";
            M5(ref name);
            Console.WriteLine(name);//乔丹

            int[] arrInt = new int[] { 1, 2, 3, 4, 5, 6, 7, 8 };
            M6(ref arrInt);
            //0000000
            for (int i = 0; i < arrInt.Length; i++)
            {
                Console.WriteLine(arrInt[i]);
            }


            int[] arrInt1 = new int[] { 1, 2, 3, 4, 5, 6, 7, 8 };
            M7(ref arrInt);
            //12345678
            for (int i = 0; i < arrInt1.Length; i++)
            {
                Console.WriteLine(arrInt1[i]);
            }

            #region MyRegion

            Console.ReadKey();
            #endregion
        }

       // 值类型 与 引用类型 作为参数  【引用传递】
        private static void M7(ref int[] arrInt)
        {
            for (int i = 0; i < arrInt.Length; i++)
            {
                arrInt[i] = 100;
            }
        }


        private static void M6(ref int[] arrInt)
        {
            arrInt = new int[arrInt.Length];
            for (int i = 0; i < arrInt.Length; i++)
            {
                arrInt[i] = arrInt[i] * 2;
            }
        }

        private static void M5(ref string name2)
        {
            name2 = "乔丹";
        }


        private static void M4(ref Person p1)
        {
            p1 = new Person();
            p1.Age++;
        }

        private static void M3(ref Person p1)
        {
            p1.Age = 1000;
            p1 = new Person();
            p1.Age = 200;
        }

        private static void M2(ref Person p1)
        {
            p1.Age++;
        }


        //值传递,传递的是栈中的内容,(对于值类型,栈中的内容就是对应的数据。对于引用类型栈中内容就是对象的地址)
        //引用传递,传递的是栈本身的地址,多个变量名实际上指向的是同一个栈变量。
        //引用传递必须使用ref关键字修饰。在方法调用的时候传递参数的时候也必须加ref 关键字
        private static void M1(ref int m)
        {
            m++;
        }
    }

    class Person
    {
        public int Age
        {
            get;
            set;
        }
    }


</pre><span style="white-space:pre"></span><span style="background-color: rgb(255, 255, 0);">值类型 与引用类型 作为参数       值传递<</span>p></p><p></p><pre name="code" class="csharp">class Program
    {
        static void Main(string[] args)
        {

            #region 值类型与引用类型介绍

            //// 值类型, 栈
            ////int  short byte char bool double float struct enum decimal 


            ////引用类型 string 数组 类 接口 委托 
            ////堆
            //string s = "a";
            //s = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";



            ////值类型
            //int n = 100;


            //int m = n;

            //m = m + 1;

            //Console.WriteLine(n);
            //Console.ReadLine();


            ////引用类型
            //Person p = new Person();
            //p.Age = 100;

            //Person p1 = p;

            //p1.Age = 120;

            //Console.WriteLine(p.Age);
            //Console.ReadKey();

            #endregion


            int n = 10;
            M1(n);
            Console.WriteLine(n);//10
            Console.ReadKey();

            Person p = new Person();
            p.Age = 100;
            M2(p);
            Console.WriteLine(p.Age);//101

            Person p1 = new Person();
            p1.Age = 100;
            M3(p1);
            Console.WriteLine(p1.Age);//1000

            Person p2 = new Person();
            p2.Age = 100;
            M4(p2);
            Console.WriteLine(p2.Age);//100

            string name = "科比";
            M5(name);
            Console.WriteLine(name);//科比

            int[] arrInt = new int[] { 1, 2, 3, 4, 5, 6, 7, 8 };
            M6(arrInt);
            //12345678
            for (int i = 0; i < arrInt.Length; i++)
            {
                Console.WriteLine(arrInt[i]);
            }

            int[] arrInt1 = new int[] { 1, 2, 3, 4, 5, 6, 7, 8 };
            M7(arrInt1);
            //100,100,100,100,100,100,100,100
            for (int i = 0; i < arrInt1.Length; i++)
            {
                Console.WriteLine(arrInt1[i]);
            }

            Console.ReadKey();
        }


        #region 值类型 与 引用类型 作为参数  【值传递】


        //值传递:

        private static void M7(int[] arrInt)
        {
            for (int i = 0; i < arrInt.Length; i++)
            {
                arrInt[i] = 100;
            }
        }
        private static void M6(int[] arrInt)
        {
            arrInt = new int[arrInt.Length];
            for (int i = 0; i < arrInt.Length; i++)
            {
                arrInt[i] = arrInt[i] * 2;
            }
        }


        private static void M5(string name2)
        {
            name2 = "乔丹";
        }

        private static void M4(Person p1)
        {
            p1 = new Person();
            p1.Age++;
        }

        private static void M3(Person p1)
        {
            p1.Age = 1000;
            p1 = new Person();
            p1.Age = 200;
        }
        private static void M2(Person p1)
        {
            p1.Age++;
        }
        private static void M1(int m)
        {
            m++;
        }
}

值类型和引用类型的区别

1.将一个值类型变量赋给另一个值类型变量时,将复制包含的值。引用类型变量的赋值只复制对对象的引用,而不复制对象本身。
2.值类型不可能派生出新的类型:所有的值类型均隐式派生自System.ValueType。但与引用类型相同的是,结构也可以实现接口。
3.值类型不可能包含null值:
4.每种值类型均有一个隐式的默认构造函数来初始化该类型的默认值。 

然而可空类型功能允许将null赋给值类型。

堆和栈的区别
栈是编译期间就分配好的内存空间,因此你的代码中必须就栈的大小有明确的定义;局部值类型变量、值类型参数等都在栈内存
中。
堆是程序运行期间动态分配的内存空间,你可以根据程序的运行情况确定要分配的堆内存的大小。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值