unity拾杂记录

c#中的静态类

//ctrl +K+F
//Shift + Alt + F   VIsualStudio力扣整理

静态类的主要特点和用途包括:

  1. 仅包含静态成员:静态类只能包含静态成员。这意味着你不能在静态类中声明实例成员(即非静态成员)。

  2. 不能被实例化:由于静态类仅包含静态成员,因此你不能使用 new 关键字来创建静态类的实例。

  3. 全局访问:静态类的成员可以通过类名直接访问,这使得它们类似于全局函数或全局变量,但它们在逻辑上属于一个类,这有助于组织代码和提供命名空间支持。

  4. 作为工具类:静态类经常被用作工具类,其中包含了一组静态方法,这些方法提供了执行某些操作的功能,而不需要保留任何状态(即不需要实例变量)。

  5. 单例模式的替代:在某些情况下,如果你有一个类,它应该只有一个实例,并且你希望这个实例在全局范围内可访问,你可能会考虑使用单例模式。然而,如果这个类不需要维护任何状态(即它只包含静态方法),那么使用静态类可能是一个更简单、更直观的选择。

using System;  
  
public static class MathUtils  
{  
    // 静态方法  
    public static int Square(int x)  
    {  
        return x * x;  
    }  
  
    // 静态属性  
    public static int MaxValue { get; } = int.MaxValue;  
  
    // 注意:静态类不能包含实例构造函数  
    // 如果尝试添加非静态成员或非静态构造函数,编译器将报错  
}  
  
class Program  
{  
    static void Main(string[] args)  
    {  
        // 直接通过类名访问静态成员  
        Console.WriteLine(MathUtils.Square(5)); // 输出 25  
        Console.WriteLine(MathUtils.MaxValue);  // 输出 int 的最大值  
    }  
}

 代码深究:

声明的静态类可以去掉public吗

对于顶级类,默认是internal的。

在C#中,public static class MathUtils 中的 public 关键字是访问修饰符,它指定了这个类的可访问性。public 意味着这个类是公开的,可以在任何其他类中访问,只要它们位于相同的程序集(assembly)中或者通过适当的引用关系

然而,public 并不是必须的。你可以根据需要将 MathUtils 类声明为其他访问级别,比如 internalprotected internal(在类的上下文中,这实际上简化为 internal,因为静态类不能是继承的一部分)、或者 private(但这在顶级类中是不可能的,因为顶级类默认就是 internal 或 public 的,并且你不能将顶级类声明为 private 或 protected)。

命名空间、程序集、模块、框架

1. 命名空间的作用

命名空间(Namespace)是C#中用于组织类的逻辑结构的一种方式。

它主要用来解决在大型项目中可能出现的类名冲突问题

通过在不同的命名空间中定义相同名称的类,可以确保它们的唯一性。

命名空间可以嵌套,即一个命名空间可以包含另一个命名空间。

2. public和internal与命名空间的关系

  • public:当类型(如类、接口、结构等)被声明为public时,该类型不仅可以在其所在的命名空间内被访问,还可以在命名空间外部被访问,前提是调用者能够通过引用(如程序集引用)访问到该类型所在的程序集。这意味着public类型可以跨命名空间、跨程序集进行访问。

  • internal:当类型被声明为internal时,该类型的访问被限制在其所在的程序集内部。这意味着即使两个类型位于相同的命名空间中,但如果它们分属不同的程序集,那么一个程序集中的internal类型在另一个程序集中是不可访问的。此外,internal类型也不能通过命名空间直接访问,因为命名空间只是逻辑上的分组,真正的访问控制是由程序集边界决定的。

3.程序集边界

这是因为在.NET中,程序集是类型定义和访问控制最小单位。程序集内部的类型可以相互访问(根据访问修饰符的规则),但程序集外部的代码则无法直接访问程序集内部的internal类型或成员,除非通过反射等高级技术。

4.程序集与命名空间的物理与逻辑差异

程序集是物理上的单位,它包含了编译后的代码和资源文件;而命名空间则是逻辑上的单位,用于组织和管理类型。一个程序集可以包含多个命名空间,而一个命名空间也可能分布在多个程序集中。然而,从访问控制的角度来看,程序集是更基本的单位,因为internal访问修饰符的作用范围是基于程序集边界的。

5.程序集与创建的项目(文件夹)

在.NET中,程序集(Assembly)是一个编译后的代码集合,它包含了一个或多个已编译的.NET模块(通常是DLL或EXE文件),以及程序集清单(Assembly Manifest)。程序集清单包含了程序集的元数据,如版本信息、文化信息、程序集依赖项等。

当你使用Visual Studio或任何支持.NET的IDE创建一个新项目时,你实际上是在创建一个新的程序集。但是,要注意的是,程序集并不直接等同于项目文件夹。项目文件夹包含了源代码文件、资源文件、配置文件等,而程序集是这些文件经过编译后生成的产物

具体来说:

  • 项目文件夹:这是你在IDE中看到的目录结构,包含了你的源代码(如.cs文件)、资源文件(如图标、图片等)、配置文件(如app.config或web.config)等。这些文件在编译之前存在于你的计算机上。

  • 程序集:当你编译项目时,编译器会处理项目文件夹中的源代码和资源文件,并将它们转换成一个或多个程序集文件(DLL或EXE)。这些程序集文件包含了编译后的代码、元数据、资源等,并可以被.NET运行时环境加载和执行。

因此,当你创建一个新的项目时,你实际上是在为未来的程序集创建源代码和资源。编译后,这些源代码和资源将被打包成一个或多个程序集文件。

在Visual Studio中,你可以通过“解决方案资源管理器”查看项目文件夹的内容,而通过“输出”窗口或项目属性中的“输出路径”可以查看编译后生成的程序集文件的位置

总结来说

项目文件夹包含了创建程序集所需的源代码和资源,

而程序集则是这些源代码和资源编译后的结果

程序集是你创建的项目经过编译后生成的产物,而不是项目文件夹本身。

6.模块是程序集的一部分

在.NET框架中,模块(Module)确实是程序集(Assembly)的一部分。

在.NET的编译和程序集构建的上下文中,模块通常指的是编译后的代码块,这些代码块可以单独编译,但最终需要被合并(或“链接”)到一个或多个程序集中。

这些模块在文件系统层面可能以.netmodule文件的形式存在,但更常见的是它们作为程序集(DLL或EXE)中的一部分存在,而不作为单独的文件。

然而,在日常的.NET开发讨论中,人们可能并不严格区分“模块”和“程序集中的一部分”。当谈到DLL或EXE文件时,我们通常会说它们包含了多个类型(如类、接口、结构体等),这些类型共同构成了程序集的功能集合。在这个意义上,每个类型或类型组都可以被视为程序集的一个“模块”,尽管这种用法并不完全准确。

更准确地说,程序集是.NET中代码组织、重用、安全性和版本控制的基本单位。它包含了编译后的代码(可能来自多个源代码文件)、元数据(描述程序集中类型的信息)、资源(如图标、字符串等)以及程序集清单(包含程序集的元数据,如名称、版本、依赖项等)。程序集可以是DLL文件(用于类库),也可以是EXE文件(用于可执行程序)

因此,当你说“模块是程序集的一部分”时,虽然这个表述在严格的编译和程序集构建上下文中可能不完全准确(因为“模块”通常指的是.netmodule文件),但在更广泛的讨论中,它传达了类型或代码块作为程序集组成部分的概念,这是正确的。

7.程序集并不一定有框架

程序集是.NET中的一个核心概念,它是编译后的代码(包括中间语言IL代码)和元数据的集合,这些代码和元数据被打包成一个或多个文件(通常是DLL或EXE文件),用于在.NET环境中部署、版本控制和重用。

框架(Framework)则是一个更广泛的概念,它通常指的是一组预构建的、可复用的软件组件,这些组件为开发者提供了构建应用程序所需的基础结构和功能框架可能还包含多个程序集,以及一系列的设计模式、最佳实践和文档,以帮助开发者更有效地构建和部署应用程序。

因此,程序集和框架之间并没有直接的依赖关系。一个程序集可以在没有框架的情况下独立存在和运行(只要它包含了所有必要的依赖项),而一个框架则可能由多个程序集和其他组件组成。

在.NET环境中,程序集是构建应用程序的基本单元,而框架则提供了一套更高级别的抽象和工具,以帮助开发者更高效地构建应用程序。然而,并不是所有的程序集都依赖于某个特定的框架,它们可以独立存在,也可以与其他程序集或框架一起工作。

VIsual Studio相关

编译器不是IDE(集成开发环境)

在IDE中,编译器(Compiler)通常被集成为一个组件,用于将用户编写的源代码编译成可执行文件或库文件。

IDE(集成开发环境)

IDE是一种用于提供程序开发所需的各种工具的软件应用。它通常包括代码编辑器、编译器、调试器、图形用户界面工具以及用于自动化构建过程的工具。IDE的主要目的是通过集成各种开发工具来提高开发效率,简化开发流程。

IDE的功能差异:虽然不同的IDE在用户界面、代码编辑功能、调试工具等方面可能存在差异,但这些差异主要影响的是开发者的开发效率和体验,而不是最终编译出的代码的质量或能力。

Visual Studio是IDE

Visual Studio是由微软(Microsoft)开发的一款功能强大的集成开发环境(IDE),它支持多种编程语言,包括C#、C++、Visual Basic、JavaScript等

并且可以用于开发各种类型的应用程序(于是就IDE中,用编译器,写出c#脚本,再喂给unity用)

在Unity中使用Visual Studio编写的脚本,与在其他IDE(如MonoDevelop等)中编写的脚本,其编译器产出可用代码的能力在本质上是没有区别的。这是因为无论是Visual Studio还是其他IDE,它们都是作为代码编辑器或开发环境(IDE)来使用,而最终编译成Unity可执行的代码是由Unity引擎内部的编译器完成的。

Unity与Visual Studio

Unity的集成:Unity与Visual Studio等IDE之间有良好的集成,这主要是通过Visual Studio Tools for Unity等插件实现的。

这些插件使得开发者可以在Unity编辑器内部直接打开Visual Studio来编辑脚本,并且能够在Unity编辑器中实时看到脚本修改的效果。(看到的是c#脚本,而不是unity引擎的编译)

然而,这种集成主要影响的是开发流程和工作效率,而不是编译结果。

显式转换(Explicit Conversion)

显式转换是当你从一个类型转换为另一个类型时,这种转换可能不安全或数据可能会丢失,因此编译器不会自动进行这种转换,而是要求开发者显式地指定转换。这种转换通常是通过类型转换语法(Type)value来完成的。

在自定义类型(如类或结构体)中,如果你想要支持类型之间的显式转换,你可以在你的类中使用explicit关键字来定义一个转换运算符。

示例

假设你有一个表示温度的类,支持摄氏度和华氏度之间的转换,但你想要这种转换是显式的:

public class Temperature  
{  
    private double celsius;  
  
    // 构造函数  
    public Temperature(double celsius)  
    {  
        this.celsius = celsius;  
    }  
  
    // 显式转换到Fahrenheit  
    public static explicit operator double(Temperature temp)  
    {  
        return (temp.celsius * 9 / 5) + 32;  
    }  
  
    // 示例:显式转换使用  
    public static void Main()  
    {  
        Temperature temp = new Temperature(25);  
        double fahrenheit = (double)temp; // 这里需要显式转换  
        Console.WriteLine($"Temperature in Fahrenheit: {fahrenheit}");  
    }  
}

    public static explicit operator double(Temperature temp)  
    {  
        return (temp.celsius * 9 / 5) + 32;  
    }  

static void Main(string[] args) 

关于args

首先,这个参数是可选的,它允许程序接收命令行参数。如果你不需要从命令行接收任何参数,你可以省略这个参数。

在C#(以及许多其他编程语言中)的Main方法里,参数名args并不是某个特定缩写的广泛公认含义,而是一个约定俗成的命名习惯。这里的args通常被理解为“arguments”(参数)的缩写,尽管它不是严格意义上的缩写,因为并没有去掉任何字母。然而,由于它在编程中如此常见,以至于它几乎已经成为了“命令行参数”的代名词。

string[] args 是 Main 方法的一个参数,它是一个字符串数组。这个参数允许你从命令行接收参数到你的程序中。当你在命令行或终端中运行程序时,可以在程序名之后添加一些文本(称为命令行参数),这些文本会被作为字符串数组传递给 Main 方法中的 args 参数

例如,如果你有一个程序名为 MyApp.exe,并且你在命令行中这样运行它:

MyApp.exe param1 param2

 那么,Main 方法中的 args 数组将包含两个字符串:"param1" 和 "param2"。这使得你的程序能够处理来自外部的输入,从而增加了程序的灵活性和实用性。

关于static

Main 方法必须是静态的(static),因为程序在启动时不需要类的实例就可以直接调用它。

关于void

在大多数情况下,Main 方法返回类型为 void,意味着它不返回任何值,且可以换为int,只能这两种返回类型。

换成int,你可以通过退出代码向调用程序(如批处理脚本、其他程序或操作系统本身)提供更丰富的信息,关于你的程序是如何结束的。例如,你可以返回一个非零值来表示发生了某种类型的错误。

然而,从C# 7.1开始,你可以使用 Task 或 Task<int> 作为 Main 方法的返回类型,以支持异步编程。但这并不是必需的,并且仍然需要.NET Core或.NET 5/6/7等较新的框架支持。

关于Main

方法名必须是 Main,因为这是C#编译器和运行时环境识别为程序入口点的约定。

综上,必须保留的(void可变int,出于程序退出代码(Exit Code)的考虑)

static void Main()

  • 11
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值