C#的学习基础篇(2)

目录

1. 变量的作用域有哪些?

        1.1 局部变量:

        1.2 块级作用域:

        1.3 方法参数作用域

        1.4 全局变量

        1.5 静态变量作用域

2. 成员变量和静态变量的区别?      

3.  利用递归,写个文件目录遍历,打印出文件名、扩展名、文件大小

4. 简述访问修饰符有几种,各有什么不同?

5.  重点比较public、protected、private的区别



1. 变量的作用域有哪些?

        变量的作用域分别有:局部变量;块级作用域;方法参数作用域;全局变量;静态变量作用域; 

        下面分别堆这些变量的作用域进行详细讲解:

        1.1 局部变量:

        局部变量是在方法、构造函数、属性或任何嵌套的代码块内声明的变量。它们的作用域仅限于它们被声明的代码块,通常是大括号 {} 内的内容。一旦控制流离开该代码块,局部变量就会被销毁。这意味着局部变量只在其声明的范围内可见,并且在每次进入此范围时都会重新创建。

namespace DjConsoleApp0527
{
    internal class Question
    {
        void MyMethod1()
        {
            int localVar = 10; // 局部变量
            if (true)
            {
                Console.WriteLine(localVar); // 可以访问
            }
            Console.WriteLine(localVar); // 可以访问
        }
        // 在MyMethod()之外无法访问localVar
        Console.WriteLine(localVar)
    }

}

        程序显示结果将会是:

        1.2 块级作用域:

        块级作用域指的是在任何由大括号 {} 包围的代码块内部声明的变量。这些变量仅在该代码块内可见,一旦代码块执行完毕,变量就会被销毁。这与局部变量相似,但特别强调了在条件语句(如 iffor 循环)中的使用。

 void MyMethod2()
 {
     if (true)
     {
         int blockScopedVar = 20; // 块级作用域变量
         Console.WriteLine(blockScopedVar);
     }
   Console.WriteLine(blockScopedVar); // 错误:blockScopedVar在此处不可见
 }

        程序显示结果将会是:

        1.3 方法参数作用域

        方法参数是在方法签名中声明的变量,用于接收传递给方法的值,它们的作用域限于整个方法体内,即从方法的开始到结束,41方法参数只能在方法内部被访问。

 void MyMethod3(int param)
 {
     Console.WriteLine(param); // 可以访问
 }

//Console.WriteLine(param)
 //param在此处不可见

        只在方法体内生效

        1.4 全局变量

        在C#中,严格意义上不存在“全局变量”。但是,类的字段(尤其是静态字段)有时被称作全局变量,因为它们在整个类的生命周期中存在,并且在类的任何方法中都可以访问。然而,它们并不是真正意义上的全局,因为它们仍然受限于类的边界。

class MyClass
{
    int memberVar = 30; // 成员变量,在整个类中可见
}
        1.5 静态变量作用域

        静态变量是在类级别上声明的,使用关键字 static;它们在所有实例共享同一份副本,即所有类的实例访问的是同一个静态变量。静态变量在整个应用程序运行期间存在,直到应用程序终止。它们可以在类的任何静态上下文中访问,包括静态方法和静态构造函数。

class MyClass
{
    static int staticVar = 40; // 静态变量,在整个类中可见
}
2. 成员变量和静态变量的区别?      

        成员变量(Instance Variables):

  •         所属范围:成员变量属于每个类的实例(对象),也就是说,每当创建一个新的对象时,每个对象都会拥有自己独立的一份成员变量的副本。
  •         存活时间:成员变量的生命周期与对象的生命周期绑定。当对象创建时,成员变量随之创建;当对象被垃圾回收时,成员变量也随之消失。
  •         存储位置:成员变量存储在堆内存中,作为对象的一部分。
  •         调用方式:成员变量只能通过对象实例来访问和修改。

        静态变量(Static Variables):

  •         所属范围:静态变量属于类本身,而不是类的任何特定实例。这意味着无论创建了多少个对象,静态变量都只有一个副本,所有实例共享这个副本。
  •         存活时间:静态变量的生命周期与类的生命周期绑定。当类加载时,静态变量被创建;当类卸载时,静态变量才消失。
    •         存储位置:静态变量存储在方法区(也称为永久代,在Java中)或类的元数据区域(在.NET中),而不是堆内存。
  •         调用方式:静态变量可以通过类名直接访问,也可以通过对象实例访问,但推荐使用类名访问,以表明其静态性质。

        成员变量属于对象级别,每个对象创建时进行初始化,每个对象实例自己来独立维护这个成员变了;静态变量属于类级别,当类加载时它就会被创建,比对象更早(创建一个工具类,工具类的方法都习惯使用静态)独一份;相比静态变量的性能是高于成本变量;如果复用我们习惯使用静态的,如果各自独立使用,也不需要立即使用,用的时候在创建,我们习惯使用实例变量。

        直接代码展示:

        这个代码已经加上了static,全局变量只需要去掉static即可。

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

namespace DjConsoleApp0527
{
    internal class StaticVar
    {
        static public int num;//成员变量
        public void count()
        {
            num++;
        }

        public int get()
        { 
            return num; 
        }
    }
}


//调用函数
using DjConsoleApp0527;
#region
StaticVar sv = new  StaticVar();
sv.count();
sv.count();
sv.count();
Console.WriteLine(sv.get());

StaticVar sv2= new StaticVar(); 
sv2.count();
sv2.count();
sv2.count();

Console.WriteLine(sv2.get());

        结果的比较:

         局变量的结果图: 

        静态变量作用域的结果图:

3.  利用递归,写个文件目录遍历,打印出文件名、扩展名、文件大小

        这里做个递归的练习,补充一下C#方法的知识量。

        首先,现在使用的项目下添加一个DirectoryTraversa类

        然后,根据以下步骤做出这个作业:

  1. 创建一个递归函数,接受目录路径作为参数。
  2. 在函数中,使用DirectoryInfoFileInfo类来获取目录和文件信息。
  3. 使用GetFilesGetDirectories方法来获取目录下的文件和子目录。
  4. 对每个文件,打印文件名、扩展名和大小。
  5. 对每个子目录,递归调用该函数。

        代码如下:

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

namespace DjConsoleApp0527
{
    internal class DirectoryTraversa
    {
        public void TraverseDirectory(string Path)
        {
           /* try
            {*/
                DirectoryInfo dirInfo = new DirectoryInfo(Path);

                if (dirInfo.Exists)
                {
                    // 获取目录下的所有文件
                    FileInfo[] files = dirInfo.GetFiles();
                    foreach (FileInfo file in files)
                    {
                        Console.WriteLine("文件名{0},拓展名{1},文件大小{2},",file.Name,file.Extension,file.Length);
                    }

                    // 获取目录下的所有子目录
                    DirectoryInfo[] subDirs = dirInfo.GetDirectories();
                    foreach (DirectoryInfo subDir in subDirs)
                    {
                        // 递归调用
                        TraverseDirectory(subDir.FullName);
                    }
                }
                else
                {
                    Console.WriteLine("Directory '{0}' does not exist.",Path);
                }
            }
            /*catch (UnauthorizedAccessException)
            {
                Console.WriteLine($"Access to directory '{Path}' is denied.");
            }
            catch (DirectoryNotFoundException)
            {
                Console.WriteLine($"Directory '{Path}' was not found.");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Error accessing directory '{Path}': {ex.Message}");
            }*/
        //}

    }
}

        调用函数:

using DjConsoleApp0527;

DirectoryTraversa directory=new DirectoryTraversa();
string Path= @"D:\NLP\weibo\pachon";
directory.TraverseDirectory(Path);

        输出的结果:

可以看出已经实现了这个功能,做作业中我发现:在C#中,异常既可以由系统自动抛出,也可以由程序员显式地抛出,所以我就注释了异常抛出的代码

4. 简述访问修饰符有几种,各有什么不同?

        比较一下java和C#的访问修饰符:

  •         Java:public、protected、默认、private
  •         C#:public、protected、private、internal、protected internal:

        在C#中访问修饰符有: 

  1. public(公开的))

    描述:公共访问。成员可以被任何其他代码访问,无论这些代码是在同一个类、同一个命名空间、同一个程序集还是不同的程序集中。
  2. private(私有的)

    描述:私有访问。成员仅在其声明所在的类中可见。即使在派生类中也不可访问。
  3. protected(受保护的)

    描述:保护访问。成员在其声明所在的类及其派生类中可见。这使得基类的成员可以在派生类中被访问。
  4. internal(程序集内部的)

    描述:内部访问。成员仅在包含其声明的程序集内可见。这意味着其他在同一程序集内的类可以访问这些成员,但不同程序集中的类则不能。
  5. protected internal(只有本程序内或者继承于该类的类型可以访问)

    描述:内部保护访问。成员在包含其声明的程序集内以及派生类中可见。这意味着成员既具有protected的特性也具有internal的特性。
5.  重点比较public、protected、private的区别
  1. public:

    描述: 成员对所有代码开放,无论这些代码位于何处,即在同一个类、同一个包(Java中)、同一个命名空间(C#中)、同一个项目或完全不同的项目中。
  2. protected:

    描述: 成员对同一类、同一包(Java中)或同一命名空间(C#中)内的代码开放,同时对所有派生类开放,不论这些派生类位于何处。这意味着protected成员可以被子类访问,从而支持继承和多态。
  3. private:

    描述: 成员仅对声明它的类开放,即只有该类内部的方法可以访问这些成员。private成员对类的外部(包括子类)是不可见的,这提供了最高级别的封装和数据保护。

        直接上代码:   

        创建两个类一个BaseClass.cs 基类和DerivedClass.cs 派生类:

        BaseClass.cs 基类

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

namespace DjConsoleApp0527
{
    internal class BaseClass
    {
        public int pc;
        protected int pd;
        private int pe;

        public void pcm()
        {
            Console.WriteLine("pcm");
        }
        protected void pdm()
        {
            Console.WriteLine("pdm");
        }
        private void pem()
        {
            Console.WriteLine("pem");
        }

    }
}

        DerivedClass.cs 派生类:

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

namespace DjConsoleApp0527
{
    internal class DerivedClass : BaseClass
    {
        public void accessMember()
        {
            pc = 10;    //直接访问父类的public属性
            pd = 20;    //直接访问父类的protected属性
 //pe = 30;不能直接访问父类的private属性

            pcm();      //直接访问父类的public方法
            pdm();      //直接访问父类的protected方法
            //pem();//不能直接访问父类的private方法
        }
    }
}

        调用:

using DjConsoleApp0527;

DerivedClass dc = new DerivedClass();
dc.accessMember();  //外部类通过派生类去访问基类

dc.pc = 10;     //public属性在哪都可以
//dc.pd = 20;     //报错:外部类属性不能直接访问,只能子类去访问

dc.pcm();       //public方法在哪都可以
//dc.pdm();       //报错:外部类方法不能直接访问,只能子类去访问

从以上代码应该可以直观的看出它们的不同了吧。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值