变量的作用域
在C#中,变量的作用域分为:局部变量、块作用域变量、方法参数、全局变量,静态变量,且各自具有独特的特性和作用域规则,下面是对它们的总结:
-
局部变量:定义在方法体、循环体、条件语句等内部的变量,仅在该代码块内有效。每次方法调用或循环迭代时,局部变量都会重新创建和销毁。
void xx() { int a = 10; //局部变量,方法体内,作用域 a = 20; }
-
块作用域变量:在一对花括号
{}
内定义的变量,其生命周期限于该代码块。这提供了更细粒度的作用域控制,有助于减少名称冲突和提升代码的清晰度。{ int x = 0; //块的变量,作用域,块内有效 x = 10; }
-
方法参数:作为方法签名一部分的变量,仅在该方法的执行上下文中有效。这些参数用于接收外部传入的数据,是局部变量的一种特殊形式。
void max(int a,int b) { a=10; b=10;//a与b都是方法参数变量,在方法内部有用,在外面无法访问。 }
-
全局变量:在程序的任何地方都可以被访问。它的作用域最大。
-
静态变量:静态变量在C#中的作用域是整个类级别,这意味着一旦在类中定义了一个静态变量,它就可以在该类的任何成员方法或属性中被访问,不论这些成员是静态的还是非静态的。
成员变量和静态变量的区别
成员变量和静态变量在C#中扮演着不同角色,主要区别聚焦于它们的生命周期、存储方式以及使用场景,这直接影响到程序的设计和性能。
成员变量的本质特点是与对象实例紧密绑定。每当一个新的对象实例被创建时,成员变量也会随之初始化,每个实例都拥有这些变量的独立副本。这意味着,即使同个类的不同对象,它们的成员变量可以有不同的值,反映了每个对象独特的状态。这种设计适合存储那些随对象创建而变化、或需根据不同实例进行独立管理的信息。
静态变量则与类自身相关联,而不是任何单一实例。静态变量在类首次被加载到内存时创建,且在整个应用程序运行期间只存在一份。所有该类的实例共享这一份静态变量,任何实例对静态变量的修改都会影响到其他实例。静态变量适用于存储那些不依赖于特定对象实例、需要在类的所有实例间共享的数据,或者是类的全局配置、计数器等。
关于性能,静态变量由于其唯一性和生命周期长,访问时相对更快,减少了实例化对象的开销,尤其在频繁访问共享数据的场景下更为高效。然而,这也意味着静态变量的使用需要更加谨慎,以避免潜在的并发问题和状态混乱。
选择成员变量还是静态变量,关键在于理解数据的用途和是否需要跨实例共享:
- 如果数据逻辑上属于每个对象自己的状态,且不同实例间应有所不同,应使用成员变量。
- 若数据是类级别的共享资源,或作为工具方法的一部分(如帮助类中的工具函数),静态变量则是更合适的选择。
总之,成员变量提供了对象级别的数据隔离和独立性,而静态变量则促进了数据的跨实例共享和全局访问,两者各有优势,需根据具体需求合理选用。
利用递归,写个文件目录遍历
首先我们先写出一个公共的方法:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
namespace DJConsoleProject
{
internal class DirectoryTraversal
{
public void TraverseDirectory(string path)
{
// 获取指定路径下的所有子目录和文件
string[] files = Directory.GetFiles(path);
string[] directories = Directory.GetDirectories(path);
// 遍历文件
foreach (string file in files)
{
FileInfo fileInfo = new FileInfo(file);
Console.WriteLine($"文件名: {fileInfo.Name}, 扩展名: {fileInfo.Extension}, 大小: {fileInfo.Length} 字节");
}
// 遍历目录,并递归调用本方法
foreach (string directory in directories)
{
TraverseDirectory(directory);
}
}
}
}
获取文件和目录
-
Directory.GetFiles(path)
:这个方法接收一个字符串参数path
,表示要查询的目录路径,返回一个字符串数组,包含指定路径下的所有文件的完整路径。 -
Directory.GetDirectories(path)
:类似地,这个方法也是接收一个目录路径参数,返回一个字符串数组,包含该路径下所有子目录的完整路径。
遍历并打印文件信息
-
使用
foreach
循环遍历files
数组中的每个元素(即每个文件的完整路径)。 -
对于每个文件路径,通过
FileInfo
类来获取更多文件详情。FileInfo fileInfo = new FileInfo(file);
-
然后,使用
Console.WriteLine
打印出文件的相关信息:fileInfo.Name
:获取文件名(不含路径和扩展名)。fileInfo.Extension
:获取文件的扩展名(包括点号)。fileInfo.Length
:获取文件的大小(以字节为单位)。
递归遍历子目录
-
使用另一个
foreach
循环遍历directories
数组,即遍历所有子目录的路径。 -
对于每个子目录,递归调用
TraverseDirectory(directory)
方法。这样,程序会深入到每个子目录中重复上述过程,直到没有更多的子目录为止,实现了对整个目录树的遍历。
通过启动类调用所写的方法
using DJConsoleProject;
DirectoryTraversal directoryTraversal= new DirectoryTraversal();
directoryTraversal.TraverseDirectory("D:/作业/未分配的城市");
结果:
访问修饰符的种类及不同
- 访问修饰符的种类有:public,protected,private,internal, protected internal五种。
- 访问修饰符的不同:
- public:成员可以被任何代码访问。
- private:成员只能被定义它们的类或结构中的代码访问。
- protected:成员只能被定义它们的类或从该类继承的子类中的代码访问。
- internal:成员只能被定义它们的同一程序集中的代码访问。
- protected internal:成员可以被定义它们的同一程序集中的代码或者从该类继承的子类中的代码访问(无论子类是否在同一个程序集中)。
比较public、protected、private的区别
在C#中,`public`、`protected`、`private` 是三种基本的访问修饰符,它们控制着类成员的可访问范围。下面是它们之间的主要区别:
1. public:
- 访问范围: `public` 成员可以在任何地方被访问,无论是同一个类内部、派生类、同一程序集或其他程序集中的类。
- 特点: 提供了最大的访问权限,适合那些需要被广泛使用的接口或公共功能。
2. protected:
- 访问范围: `protected` 成员可以被同一类内部和任何派生类访问,无论派生类是否在同一个程序集中,但不能被类的外部直接访问。特别注意,被此修饰符修饰的类成员它只能被自身还有子类访问,不能被子类的子类访问。其实就相当于它在被子类继承后,自动的将protected权限变成了private权限。
- 特点: 适合设计意图是让子类能够访问或重写,但不希望对外界公开的成员。
3. private:
- 访问范围: `private` 成员只能被定义它们的类内部访问,对于派生类或类的外部都是不可见的。
- 特点: 提供了最严格的封装,用于隐藏类的内部实现细节,确保数据安全和逻辑完整性。
简而言之,`public` 成员是完全公开的,`protected` 成员在类及其派生类内部可见,而 `private` 成员仅在定义它们的类内部可用。选择哪种访问修饰符取决于你希望如何控制类成员的可见性和可访问性,以此来实现更好的封装、继承和多态性设计。