[编程开发] C#零基础该怎么自学入门?

[复制链接]
lianyuan1986 发表于 2023-12-13 08:21:03|来自:北京 | 显示全部楼层 |阅读模式
能推荐一些书籍和视频吗?感谢!
全部回复5 显示全部楼层
第一浪 发表于 2023-12-13 08:21:58|来自:北京 | 显示全部楼层
前言

    本文来源于知乎的一个提问,提问的是一个大一软件工程专业的学生,他想要自学C#但是不知道该怎么去学,这让他感到很迷茫,希望有人能给他一些建议和提供一些学习方向。
个人建议


  • 确认目标:自学C#首先你需要大概了解该门语言的发展、前景和基本特点,从自身实际情况和方向出发确认学习的必要性。
  • 制定学习计划:制定一个详细的学习计划(比如每天学习一个C#知识点),这将有助于你更好地组织学习过程。
  • 微软官方文档是良好的起点:对于C#的学习,微软官方文档是一个非常好的资源。这些文档提供了详细的说明和示例代码,涵盖了C#的各个方面。按照文档的目录逐步学习,可以让你循序渐进地掌握语言的各个语法和概念。
  • 多动手多实践:熟能生巧,学习的过程中除了阅读文档和示例代码以外,实践也是非常重要的。通过动手去实践所学的知识点,从而加深你对代码的理解和提高编程能力。
  • 寻找其他资源:除了微软官方文档,还有许多其他优质的学习资源可供选择,如在线教程、视频课程和编程社区。通过结合不同的学习资源,你可以获得更全面的学习体验。
温馨提示:自学的过程是一个枯燥无味的过程,通过制定有效的学习计划鞭策自己每天打卡学习,从而避免三天打鱼两天晒网的情况,合理利用微软官方文档和其他学习资源,并进行实践,你将会逐步掌握C#编程技能。
合理利用微软官方文档

对于C#的学习,微软官方文档是一个非常好的资源。这些文档提供了详细的说明和示例代码,涵盖了C#的各个方面。按照文档的目录逐步学习,可以让你循序渐进地掌握语言的各个语法和概念。
微软官方文档C# 文档 - 入门、教程、参考:
https://learn.microsoft.com/zh-cn/dotnet/csharp/




C#入门





C#基础知识





C#编程指南





C#/.NET/.NET Core学习、工作、面试指南

C#/.NET/.NET Core基础知识、学习资料、视频、文章、书籍、框架、社区组织、开发必备工具和常见的面试题汇总。以及面试时需要注意的事项和优秀简历编写技巧,希望能和大家一起成长进步 。
C#/.NET/.NET Core学习、工作、面试指南






http://ASP.NET Core开发者学习指南路线图

这是一个http://ASP.NET Core开发学习路线图,提供了一个结构化的学习路线,帮助开发人员逐步掌握http://ASP.NET Core框架所需的技能,帮助开发者了解学习
http://ASP.NET Core的步骤和方向。
值得推荐的ASP.NET Core开发者学习指南路线图
指南路线GitHub地址:https://github.com/MoienTajik/AspNetCore-Developer-Roadmap/blob/master/ReadMe.zh-Hans.md




C#/.NET/.NET Core推荐学习书籍

汇总了一些很优秀的C#/.NET/.NET Core相关学习书籍,值得.Neter们或者是想要入门.Net的同学学习和专研。
C#/.NET/.NET Core推荐学习书籍(升职加薪,你值得拥有)




C#/.NET/.NET Core学习视频汇总

收集网上一些比较好的C#/.NET/.NET Core这方面的学习视频,希望能够帮助到有需要的小伙伴们。
C#/.NET/.NET Core学习视频汇总




C#/.NET/.NET Core优秀项目框架推荐

C#/.NET/.NET Core优秀项目和框架汇总,希望每个人能找到一个适合自己学习,开发的优质框架。
C#/.NET/.NET Core优秀项目框架推荐




C#/.NET/.NET Core面试宝典(基础版)

C#/.NET/.NET Core常见面试题汇总,不仅仅为了面试而学习,更多的是查漏补缺、扩充知识面和大家共同学习进步。
C#/.NET/.NET Core面试宝典(基础版)




加入DotNetGuide技术交流群

在DotNetGuide技术交流群中可以结识更多志同道合的开发者,甚至可能与其他开发者合作完成有趣的项目。通过这个群组,我们希望能够搭建一个积极向上、和谐友善的.NET技术交流平台,为广大.NET开发者带来更多的价值。
欢迎加入DotNetGuide技术交流群
funnytear 发表于 2023-12-13 08:22:24|来自:北京 | 显示全部楼层
按照这个6个步骤,零基础都能成为合格的程序员。
1、学习C#基础知识

学习任何一门编程语言,语言的基础知识都是必须要学习的,这里面涉及的内容包括:语法、关键字、事件、继承、面向对象、Linq、委托、多线程等等。
对于有编程基础的人来说,学习新的一门编程语言,以上的基础知识,基本都是稍微看一下,要使用的时候不懂再查询,基本就可以了。
但是对于初学者来说,每一个知识点都是需要花费时间去学习、练习的。对于初学者我建议,大家先总体学习一下,碰到实在无法理解的,可以先跳过。
比如很多人无法理解面向对象、多线程不会使用,都可以先跳过,不要去耗费太多的精力,很多初学者常常在某个知识点花费过长的时间,导致消耗了学习编程的动力、与耐心。


2、选择学习方向

学习.Net可以开发的内容还是比较多的,有Web开发、桌面软件开发、移动开发、游戏开发、物联网、机器学习等等,这里面涉及的知识又有:MVC、WCF、Blazor、Web API等等。
这里面涉及的知识点还是非常多,所以大家可以根据自己的兴趣,或者未来希望就业的方向选择一个方向;如果是在校学习,建议可以根据自己的兴趣选择,因为有兴趣才更加有动力学习;如果是即将毕业或者考虑转行的,建议还是以工作为主,毕竟找工作是第一紧急的事情。


3、设定学习路线

方向确认以后,就要设定学习路线了,每一个方向涉及的路线都是不一样的,比如Web开发方向,需要学习http://Asp.Net MVC或者http://Asp.net Web API;而Windows桌面软件开发,需要学习WCF或者WindowForm。



大家可以根据自己的学习路线,设定阶段性目标,逐步的完成学习任务,任何人都无法一下子把所有知识都学习完,没必要给自己太大的压力。
4、学习系统设计、框架设计能力

学完以上的内容,基础知识算是基本学习完成了,但是在实际项目开发中,我们不仅仅是能实现功能,还要考虑如何更好的完成功能的开发,以及考虑团队协作、未来功能的扩展、系统的稳定性等等。
所以我们就要学习一些必备的系统设计能力,比如代码设计、数据库设计、界面设计,一些常用的框架比如三层、DDD等知识。
这方面的知识,除了通过学习专业的知识外,建议大家可以选择一个比较流行的开源项目,着重学习以下,学习作者的架构搭建、设计的思想、以及框架的优缺点。
开源项目可以查看我之前分享:《推荐100个.Net开源项目》,选择一个学习就好。


5、不断的实践

学完任何知识,都离不开实践。编程重在编写代码,一方面是完成不同业务的开发,积累经验,还有是面对不同的场景,不同的团队,这些都是会影响你的代码设计、系统设计的,只有你经历过不同的业务、不同的场景,你才能更加深入理解编程的思想、框架的思想,从中总结出自己的一套自己的编程思维。
以后面临不同的产品、业务,自然能根据需求选择技术、编写不同的代码。


6、其他

当然了,在这过程中,程序员的内功也是非常重要的,注重代码质量,学习编程规范、设计模式等,也都是必不可少的。
具备开发能力、也注重代码质量,这才是成为一个合格的高级程序员,必备的能力。
最后,再给你分享几个有关.Net的资料:
编程乐趣:全新.NetCore/C#全栈视频教程入门教程分享编程乐趣:零基础程序员想要学好.Net,跟着这7个步骤学习就可以了【最新】.Net程序员学习路线图以及就业现状
zerosix 发表于 2023-12-13 08:22:59|来自:北京 | 显示全部楼层
<C#10 in a Nutshell> 读书笔记摘抄
和你一起成长,到我的主页,关注更多C#教程
空值运算符 Null Operators

C# 提供了三个运算符来简化处理空值的操作:空值合并运算符、空合并赋值运算符和空条件运算符(null-coalescing operator, the null-coalescing assignment operator, and the null-conditional operator)。
空合并运算符 Null-Coalescing Operator

?? 运算符是空合并运算符。也就是说,“如果左边的操作数是非空,给我;否则,给我另一个值。”例如:
string s1 = null;
string s2 = s1 ?? "nothing"; // s2 evaluates to "nothing"
如果左边的表达式不为空,则永远不会计算右边的表达式。 空合并运算符也适用于可为空的值类型。
空合并赋值运算符 Null-Coalescing Assignment Operator

??= 运算符(在 C# 8 中引入)是 null 合并赋值运算符。它表示,“如果左边的操作数为空,则将右边的操作数赋值给左边的操作数。” 考虑以下:
myVariable ??= someDefault;
这相当于:
if (myVariable == null) myVariable = someDefault;
??= 运算符在实现惰性计算属性时特别有用。
空条件运算符 Null-Conditional Operator

?. 运算符是空条件运算符或“Elvis”运算符(在Elvis表情符号之后)。 它允许您像标准点运算符一样调用方法和访问成员,除了如果左边的操作数为空,则表达式的计算结果为空,而不是抛出 NullReferenceException异常:
System.Text.StringBuilder sb = null;
string s = sb?.ToString(); // No error; s instead evaluates to null
最后一行等效于以下内容:
string s = (sb == null ? null : sb.ToString());
Null 条件表达式也适用于索引器:
string foo = null;
char? c = foo?[1]; // c is null
遇到空值时,Elvis 运算符将其余部分短路表达。在以下示例中,即使在ToString() 和 ToUpper() 之间的使用标准点运算符,s 的计算结果也是 null:
System.Text.StringBuilder sb = null;
string s = sb?.ToString().ToUpper(); // s evaluates to null without error
仅当紧靠其左侧的操作数可能时,才需要重复使用 Elvis为空。以下表达式对于 x 为 null 和 x.y 为 null 都是稳健的:
x?.y?.z
它等效于以下内容(除了 x.y 仅计算一次):
x == null ? null
: (x.y == null ? null : x.y.z)
最终表达式必须能够接受空值。以下是非法的:
System.Text.StringBuilder sb = null;
int length = sb?.ToString().Length; // Illegal : int cannot be null
我们可以通过使用可空值类型来解决这个问题:
int? length = sb?.ToString().Length; // OK: int? can be null
您还可以使用 null 条件运算符来调用 void 方法:
someObject?.SomeVoidMethod();
如果 someObject 为 null,这将变为“无操作”而不是抛出ReferenceException异常。 您可以将 null 条件运算符与常用的类型成员一起使用,包括方法、字段、属性和索引器。它 还与空合并运算符结合得很好:
System.Text.StringBuilder sb = null;
string s = sb?.ToString() ?? "nothing"; // s evaluates to "nothing"
语句 Statements

函数包含语句,这些语句按出现的顺序来顺序执行。语句块statement block是出现在大括号({} 标记)中间的一系列语句。
声明语句 Declaration Statements

变量声明引入了一个新变量,可以选择用一种表达初始化它。您可以在逗号分隔中声明多个相同类型的变量列表:
string someWord = "rosebud";
int someNumber = 42;
bool rich = true, famous = false;
常量声明类似于变量声明,只是它在声明之后不能更改,初始化必须与声明一起发生:
const double c = 2.99792458E08;
c += 10; // Compile-time Error
局部变量 Local variables
局部变量或局部常量的范围扩展到整个当前块。您不能在当前块中或在任何嵌套块中声明另一个具有相同名称的局部变量:
int x;
{
    int y;
    int x; // Error - x already defined
}
{
    int y; // OK - y not in scope
}
Console.Write (y); // Error - y is out of scope
  变量的作用域在其整个代码块中向两个方向延伸。这意味着这个例子中如果我们移动初始声明 x 到方法的底部,我们会得到同样的错误。这与 C++ 形成对比,有点奇特,因为在声明一个变量或常量之前引用它是不合法的。
表达式语句 Expression Statements

表达式语句是同时也是有效语句的表达式。一种表达语句必须要么改变状态要么调用可能改变状态的东西。改变状态本质上意味着改变一个变量。以下是可能的表达式语句:

  • 赋值表达式(包括递增和递减表达式)
  • 方法调用表达式(无效和非无效)
  • 对象实例化表达式
这里有些例子:
// Declare variables with declaration statements:
string s;
int x, y;
System.Text.StringBuilder sb;
// Expression statements
x = 1 + 2; // Assignment expression
x++; // Increment expression
y = Math.Max (x, 5); // Assignment expression
Console.WriteLine (y); // Method call expression
sb = new StringBuilder(); // Assignment expression
new StringBuilder(); // Object instantiation expression
当您调用构造函数或方法返回值一个值时,您没有义务使用这个返回值。但是,除非构造函数或方法改变状态,否则语句完全没用:
new StringBuilder(); // Legal, but useless
new string ('c', 3); // Legal, but useless
x.Equals (y); // Legal, but useless
选择语句 Selection Statements

C#有以下机制来有条件地控制程序的流程执行:

  • 选择语句(if、switch)
  • 条件运算符 (?:)
  • 循环语句(while、do-while、for、foreach)
本节介绍最简单的两种结构:if 语句和 switch语句。
The if statement
如果 bool 表达式为真,则 if 语句执行语句:
if (5 < 2 * 3)
    Console.WriteLine ("true"); // true
该语句可以是一个代码块:
if (5 < 2 * 3)
{
    Console.WriteLine ("true");
    Console.WriteLine ("Let’s move on!");
}
The else clause
if 语句可以有选择地包含 else 子句:
if (2 + 2 == 5)
    Console.WriteLine ("Does not compute");
else
    Console.WriteLine ("False"); // False
在 else 子句中,您可以嵌套另一个 if 语句:
if (2 + 2 == 5)
    Console.WriteLine ("Does not compute");
else
    if (2 + 2 == 4)
        Console.WriteLine ("Computes"); // Computes
用大括号改变执行流程
else 子句始终适用于紧接在前面的 if 语句语句块:
if (true)
    if (false)
        Console.WriteLine();
    else
        Console.WriteLine ("executes");
这在语义上与以下内容相同:
if (true)
{
    if (false)
        Console.WriteLine();
    else
        Console.WriteLine ("executes");
}
我们可以通过移动大括号来改变执行流程:
if (true)
{
    if (false)
        Console.WriteLine();
}
else
        Console.WriteLine ("does not execute");
使用大括号,您可以明确说明您的意图。这样可以提高可读性嵌套的 if 语句——即使编译器不需要。一个值得注意的例外具有以下模式:
void TellMeWhatICanDo (int age)
{
    if (age >= 35)
        Console.WriteLine ("You can be president!");
    else if (age >= 21)
        Console.WriteLine ("You can drink!");
    else if (age >= 18)
        Console.WriteLine ("You can vote!");
    else
        Console.WriteLine ("You can wait!");
}
在这里,我们安排了 if 和 else 语句来模仿其他语言的“elseif”结构(和 C# 的 #elif 预处理器指令)。 Visual Studio 的自动格式化识别这种模式并保留缩进。尽管在语义上,else 语句之后的每个 if 语句在功能上都嵌套在else 子句。
The switch statement
switch 语句让您可以根据可能的选择来分支程序执行变量可能具有的值。 switch 语句可以产生更清晰的代码而不是多个 if 语句,因为 switch 语句需要一个表达式只求值一次:
void ShowCard (int cardNumber){
    switch (cardNumber)
    {
        case 13:
            Console.WriteLine ("King");
            break;
        case 12:
            Console.WriteLine ("Queen");
            break;
        case 11:
            Console.WriteLine ("Jack");
            break;
        case -1: // Joker is -1
            goto case 12; // In this game joker counts as queen
        default: // Executes for any other cardNumber
            Console.WriteLine (cardNumber);            
            break;
        }
}
此示例演示了最常见的场景,即switch常数。当你指定一个常量时,你只能使用内置的整数类型;bool、char 和枚举类型;和字符串类型。 在每个 case 子句的末尾,您必须明确指定执行的位置 接下来,使用某种跳转语句(除非您的代码以无限循环结束)。 以下是选项:

  • break(跳转到 switch 语句的末尾)
  • goto case x(跳转到另一个 case 子句)
  • goto default(跳转到默认子句)
  • 任何其他跳转语句——即 return、throw、continue 或 goto label
当多个值应该执行相同的代码时,您可以列出共同的case顺序:
switch (cardNumber)
{
    case 13:
    case 12:
    case 11:
        Console.WriteLine ("Face card");
        break;
    default:
        Console.WriteLine ("Plain card");
        break;
}
switch 语句的这一特性对于生成更简洁的代码而言至关重要而不是多个 if-else 语句。
Switching on types
你也可以对类型使用switch(从C# 7开始):
TellMeTheType (12);
TellMeTheType ("hello");
TellMeTheType (true);
void TellMeTheType (object x) // object allows any type.
{
    switch (x)
    {
        case int i:
            Console.WriteLine ("It's an int!");
            Console.WriteLine ($"The square of {i} is {i * i}");
            break;
        case string s:
            Console.WriteLine ("It's a string");
            Console.WriteLine ($"The length of {s} is {s.Length}");
            break;
        default:
             Console.WriteLine ("I don't know what x is");
            break;
    }
}
每个 case 子句指定一个匹配的类型,以及一个变量如果匹配成功,则分配键入的值(“模式”变量)。不同于常量,对您可以使用的类型没有限制。 您可以使用 when 关键字来断言一个case:
switch (x)
{
    case bool b when b == true: // Fires only when b is true
        Console.WriteLine ("True!");
        break;
    case bool b:
        Console.WriteLine ("False!");
        break;
}
case 子句的顺序在 switching on type 时很重要(不像 when开启常量)。如果我们调换这两个case的顺序,这个例子会给出不同的结果(事实上,它甚至不会编译,因为编译器会 确定第二种情况不可达)。该规则的一个例外是default 子句,无论它出现在哪里,它总是最后执行。
如果你想switch一个类型,但对其值不感兴趣,你可以使用*discard* (_):
case DateTime _:
    Console.WriteLine ("It's a DateTime");
您可以堆叠多个 case 子句。下面代码中的Console.WriteLine将对任何大于 1,000 的浮点类型执行:
switch (x)
{
    case float f when f > 1000:
    case double d when d > 1000:
    case decimal m when m > 1000:
        Console.WriteLine ("**We can refer to x here but not f or d or m**"); // <-- HERE
        break;
}
在这个例子中,编译器让我们只在 when 子句中使用模式变量 f、d 和 m。当我们调用Console.WriteLine 时,它不知道是这三个变量的哪一个将被赋值,所以编译器认为它们全部都超出了作用域范围。 您可以在同一 switch 语句中混合和匹配常量和模式。并且您还可以switch空值:
case null:
    Console.WriteLine ("Nothing here");
    break;
Switch expressions
从 C# 8 开始,您可以在表达式的上下文中使用 switch。假如说cardNumber 是 int 类型,下面说明它的使用:
string cardName = cardNumber switch
{
    13 => "King",
    12 => "Queen",
    11 => "Jack",
    _ => "Pip card" // equivalent to 'default'
};
请注意,switch 关键字出现在变量名之后,并且case子句是表达式(以逗号结尾)而不是语句。switch表达式比对应的 switch 语句更紧凑,你可以在 LINQ 查询中使用它们(第 8 章)。 如果省略默认表达式 (_) 并且switch匹配失败,则抛出异常。 您还可以对多个值switch(元组模式):
int cardNumber = 12;
string suite = "spades";
string cardName = (cardNumber, suite) switch
{
    (13, "spades") => "King of spades",
    (13, "clubs") => "King of clubs",
    ...
};
通过使用模式可以有更多的选择。
迭代语句 Iteration Statements

C# 允许通过 while、do-while、for 和 foreach 语句重复执行一系列语句。
while and do-while loops
当 bool 表达式为真时,while 循环重复执行一段代码。在执行循环体之前测试表达式。例如, 下面写012:
int i = 0;
while (i < 3)
{
    Console.Write (i);
        i++;
}
do-while 循环在功能上与 while 循环的不同之处仅在于语句块执行后再测试表达式(确保该块始终 至少执行一次)。这是用 do-while 重写的前面的示例:
int i = 0;
do
{
    Console.WriteLine (i);
    i++;
}
while (i < 3);
for loops
for 循环类似于 while 循环,带有用于初始化和循环迭代变量的特殊子句。一个 for 循环包含三个子句,如下所示:
for (initialization-clause; condition-clause; iteration-clause)
     statement-or-statement-block
以下是每个子句的作用: 初始化子句 在循环开始之前执行;用于初始化一个或多个迭代变量 条件子句 bool 表达式,如果为真,将执行主体 迭代子句 在语句块的每次迭代后执行;通常用于更新迭代变量 例如,以下打印数字 0 到 2
for (int i = 0; i < 3; i++)
    Console.WriteLine (i);
下面打印前 10 个斐波那契数(其中每个数是前两项之和):
for (int i = 0, prevFib = 1, curFib = 1; i < 10; i++)
{
    Console.WriteLine (prevFib);
    int newFib = prevFib + curFib;
    prevFib = curFib; curFib = newFib;
}
for 语句的三个部分中的任何一个都可以省略。你可以实现一个无限循环,如下所示(尽管可以使用 while(true) 代替):
for (;;)
    Console.WriteLine ("interrupt me");
foreach loops
foreach 语句迭代可枚举对象中的每个元素。大多数表示一组或一组元素的 .NET 类型是可枚举的。例如,数组和字符串都是可枚举的。这是一个枚举的例子,字符串中的字符从第一个字符到最后一个:
foreach (char c in "beer") // c is the iteration variable
    Console.WriteLine (c);
这是输出:
b
e
e
r我们在“枚举和迭代器”中定义了可枚举对象。
跳转语句 Jump Statements

C# 跳转语句有 break、continue、goto、return 和 throw。
The break statement
break 语句结束迭代主体或switch语句的执行:
int x = 0;
while (true)
{
    if (x++ > 5)
        break; // break from the loop
}
// execution continues here after break
...
The continue statement
continue 语句放弃循环中的剩余语句并尽早开始下一次迭代。以下循环跳过偶数:
for (int i = 0; i < 10; i++)
{
    if ((i % 2) == 0) // If i is even,
        continue; // continue with next iteration
        Console.Write (i + " ");
}
// OUTPUT: 1 3 5 7 9
The goto statement
goto 语句将执行转移到语句块中的另一个标签。形式如下:
goto statement-label;
或者,在 switch 语句中使用时:
goto case case-constant; // (Only works with constants, not patterns)
标签是代码块中位于语句之前的占位符,用冒号后缀。下面的代码迭代数字 1 到 5,模仿 for 循环:
int i = 1;
startLoop:
if (i <= 5)
{
    Console.Write (i + " ");
    i++;
    goto startLoop;
}
// OUTPUT: 1 2 3 4 5
goto case case-constant 将执行转移到 switch 中的另一个 case块。
The return statement
return 语句从方法退出,如果方法是非空的话必须返回值:
decimal AsPercentage (decimal d)
{
    decimal p = d * 100m;
    return p; // Return to the calling method with value
}
return 语句可以出现在方法的任何地方(finally 块除外)并且可以多次使用。
The throw statement
throw 语句抛出异常以指示发生了错误。
if (w == null)
    throw new ArgumentNullException (...);
if (w == null)
    throw new ArgumentNullException (...);
Miscellaneous Statements

using 语句提供了一种优雅的语法在实现 了IDisposable接口的对象上调用 Dispose方法,相当于在try…catch…finally的 finally 块中。
lock 语句是调用Monitor类的 Enter 和 Exit 方法的快捷方式。
命名空间 Namespaces

名称空间是类型名称的域。类型通常组织成层级名空间,使它们更容易找到并防止冲突。例如,处理公钥加密的 RSA 类型定义在以下命名空间:
System.Security.Cryptography
名称空间构成类型名称的组成部分。以下代码调用 RSA 的创建方法:
System.Security.Cryptography.RSA rsa = System.Security.Cryptography.RSA.Create();
  命名空间独立于程序集,程序集是 .dll 文件作为部署单位。命名空间对成员可见性也没有影响——public、internal、private 等。
namespace 关键字为该块中的类型定义了一个命名空间;例子:
namespace Outer.Middle.Inner
{
    class Class1 {}
    class Class2 {}
}
命名空间中的点表示嵌套命名空间的层次结构。以下代码在语义上与前面的示例相同:
namespace Outer
{
    namespace Middle
    {
        namespace Inner
        {
            class Class1 {}
            class Class2 {}
        }
    }
}
您可以使用其完全限定名称引用类型,其中包括从最外层到最内层的所有命名空间。例如,我们可以参考前面的示例 Outer.Middle.Inner.Class1。 未在任何命名空间中定义的类型被称为驻留在全局命名空间中。全局命名空间还包括顶级命名空间,例如我们示例中的 Outer。
文件作用域命名空间 File-Scoped Namespaces (C# 10)

通常,您会希望一个文件中的所有类型都定义在一个命名空间中:
namespace MyNamespace
{
    class Class1 {}
    class Class2 {}
}
从 C# 10 开始,您可以使用文件范围的命名空间来完成此操作:
namespace MyNamespace; // Applies to everything that follows in the file.
class Class1 {} // inside MyNamespace
class Class2 {} // inside MyNamespace
文件范围的命名空间减少了混乱并消除了不必要的缩进级别。
使用using指令 The using Directive

using 指令导入一个命名空间,允许您引用类型而无需他们的完全限定名称。下面导入前面例子的 Outer.Middle.Inner 命名空间:
using Outer.Middle.Inner;
Class1 c; // Don’t need fully qualified name
  在不同的命名空间中定义相同的类型名称是合法的(并且通常是可取的)。但是,这通常是您假定使用者不太可能同时导入两个同样名字的命名空间时才这样做。一个很好的例子是 TextBox 类,在 System.Windows.Controls (WPF) 中定义和 System.Windows.Forms(Windows 窗体)。
using 指令可以嵌套在命名空间本身中以限制其范围指示。
全局使用指令 The global using Directive (C# 10)

从 C# 10 开始,如果您在 using 指令前加上 global 关键字,该指令将应用于项目或编译单元中的所有文件:
global using System;
global using System.Collection.Generic;
这使您可以集中常见的导入并避免在中重复相同的指令每个文件。 全局使用指令必须在非全局指令之前并且不能出现内部命名空间声明。 global 指令可以与 using static 一起使用。
隐式全局usings Implicit global usings
从 .NET 6 开始,项目文件允许隐式全局使用指令。如果ImplicitUsings 元素在项目文件中设置为 true(新的默认值projects),会自动导入以下命名空间:
System
System.Collections.Generic
System.IO
System.Linq
System.Net.Http
System.Threading
System.Threading.Tasks
根据项目 SDK(Web、Windows窗体、WPF 等)。
使用静态 using static

using static 指令导入类型type而不是命名空间。然后可以无限制地使用所有导入类型的静态成员。在下面的例如,我们调用 Console 类的静态 WriteLine 方法而不需要参考类型:
using static System.Console;
WriteLine ("Hello");
using static 指令导入该类型的所有可访问静态成员,包括字段、属性和嵌套类型。你也可以对枚举类型应用这个指令(第 3 章),在这种情况下它们的成员被导入。所以,如果我们导入以下枚举类型:
using static System.Windows.Visibility;
我们可以指定 Hidden 而不是 Visibility.Hidden:
var textBox = new TextBox { Visibility = Hidden }; // XAML-style
如果多个静态导入之间出现歧义,C# 编译器未能足够聪明的从上下文中推断出正确的类型,则会产生错误。
命名空间内的规则 Rules Within a Namespace

命名范围 Name scoping
在外部名称空间中声明的名称可以在内部名称空间中不加限定地使用。 在此示例中,Class1 不需要在 Inner 中进行限定:
namespace Outer
{
    class Class1 {}
    namespace Inner
    {
        class Class2 : Class1 {}
    }
}
如果你想在命名空间层次结构的不同分支中引用一个类型,你可以使用部分限定的名称。在下面的示例中,我们的 SalesReport 基于 Common.ReportBase :
namespace MyTradingCompany
{
    namespace Common
    {
        class ReportBase {}
    }
    namespace ManagementReporting
    {
        class SalesReport : Common.ReportBase {}
    }
}
名字隐藏 Name hiding
如果相同的类型名称同时出现在内部和外部命名空间中,则内部名胜出。要引用外部命名空间中的类型,您必须限定其名称:
namespace Outer
{
    class Foo { }
    namespace Inner
    {
        class Foo { }
        class Test
        {
            Foo f1; // = Outer.Inner.Foo
            Outer.Foo f2; // = Outer.Foo
        }
    }
}
  在编译时所有类型名称都转换为完全限定名称。中间语言 (IL) 代码不包含不限定或部分限定的名称。
重复命名空间 Repeated namespaces
您可以重复命名空间声明,只要名称空间不冲突:
namespace Outer.Middle.Inner
{
    class Class1 {}
}
namespace Outer.Middle.Inner
{
    class Class2 {}
}
我们甚至可以将示例分成两个源文件,这样我们就可以把每个类编译入不同的程序集。
源文件1:
namespace Outer.Middle.Inner
{
    class Class1 {}
}
源文件2:
namespace Outer.Middle.Inner
{
    class Class2 {}
}
嵌套使用指令 Nested using directives
您可以在命名空间中嵌套 using 指令。这允许您在命名空间声明中确定使用指令的使用范围。在下面的示例中,Class1 是在一个范围内可见但在另一个范围内不可见:
namespace N1
{
    class Class1 {}
}
namespace N2
{
    using N1;                // <-- HERE**
    class Class2 : Class1 {}
}
namespace N2
{
    class Class3 : Class1 {} // Compile-time error
}
为类型和命名空间指定别名 Aliasing Types and Namespaces

导入命名空间可能会导致类型名称冲突。你可以只导入你需要的特定类型而不是导入整个命名空间,只需要给每个类型一个别名:
using PropertyInfo2 = System.Reflection.PropertyInfo;
class Program { PropertyInfo2 p; }
整个命名空间可以是别名,如下所示:
using R = System.Reflection;
class Program { R.PropertyInfo p; }
高级命名空间功能 Advanced Namespace Features

Extern
外部别名允许您的程序引用两个完全相同的类型的限定名称(即名称空间和类型名称相同)。这是一个不寻常的场景,并且仅当两种类型来自不同的程序集时才会发生。考虑以下示例。 库1,编译为Widgets1.dll:
namespace Widgets
{
    public class Widget {}
}
库 2,编译为 Widgets2.dll:
namespace Widgets
{
    public class Widget {}
}
引用 Widgets1.dll 和 Widgets2.dll 的应用程序:
using Widgets;
Widget w = new Widget();
应用程序无法编译,因为 Widget 不明确。外部别名可以解决歧义。第一步是修改应用程序的 .csproj 文件,分配每个引用的唯一别名:
<ItemGroup>
  <Reference Include="Widgets1">
    <Aliases>W1</Aliases>
  </Reference>
  <Reference Include="Widgets2">
    <Aliases>W2</Aliases>
  </Reference>
</ItemGroup>第二步是使用 extern 别名指令:
extern alias W1;
extern alias W2;
W1.Widgets.Widget w1 = new W1.Widgets.Widget();
W2.Widgets.Widget w2 = new W2.Widgets.Widget();
命名空间别名限定符 Namespace alias qualifiers
正如我们之前提到的,内部命名空间中的名称隐藏了外部命名空间中的名称。然而,有时即使使用完全限定的类型名称也无法解析冲突。考虑以下示例:
namespace N
{
    class A
    {
        static void Main() => new A.B(); // Instantiate class B
        public class B {} // Nested type
    }
}
namespace A
{
    class B {}
}
Main 方法可以实例化嵌套类 B 或在命名空间 A 中的类 B。编译器总是给予在当前命名空间中的标识符以更高的优先级,在本例中是嵌套的 B 类。 要解决此类冲突,可以相对于下列的其中一个名称空间名称进行限定:

  • 全局命名空间——所有命名空间的根(用上下文关键字global标识)
  • 外部别名集
:: 标记执行名称空间别名限定。在这个例子中,我们限定使用全局命名空间(这在自动生成的代码中避免名称冲突时最常见):
namespace N
{
    class A
    {
        static void Main()
        {
            System.Console.WriteLine (new A.B());
            System.Console.WriteLine (new global::A.B());  // <-- HERE**
        }
        public class B {}
    }
}
namespace A
{
    class B {}
}
这是一个使用别名限定的示例(改编自中的示例“Extern”):
extern alias W1;
extern alias W2;
W1::Widgets.Widget w1 = new W1::Widgets.Widget();
W2::Widgets.Widget w2 = new W2::Widgets.Widget();
李强 发表于 2023-12-13 08:23:36|来自:北京 | 显示全部楼层
对于C#新手,其实微软官网就有非常全面的资料和教程(包括视频教程), 地址在这里:Developer tools, technical documentation and coding examples  
微软官方的C#文档地址为:C# docs - get started, tutorials, reference.

另外,我也在整理一些中文的保姆级的入门教程,比如: 《C#程序设计基础(入门篇)》 ,《C#+ADO.NET数据库入门教程》,《LINQ教程》 希望可以帮助到你。

我建议你可以看一看这些书籍。第一本是《Head First C#》,此本每个章节都是以图文并茂的方式来呈现内容,以案例的方式来构建知识体系,让你可以一步一步,循序渐进。
C#语言入门后,如果你还需要深入了解底层原理,那么可以看看《CLR via C#(第4版)》,此书也是由国外著作者撰写,然后翻译中文版的,读过之后会让你对C#的底层执行原理有更深刻的认知。
<a data-draft-node="block" data-draft-type="mcn-link-card" data-mcn-id="1477645328513601537">
我是Rector,码友网的创建者,码友网--一个专注.NET/.NET Core的编程资源共享社区。关注码友网,解锁更多C#&.NET开发技巧。专注.NET,我是认真的!!!
艾哥 发表于 2023-12-13 08:23:56|来自:北京 | 显示全部楼层
真正零基础不建议直接看刘铁猛老师视频,还是先看书,坚持读完c#图解这本书,最主要是要练习书中的实例,遇到不懂的知识点要学会自己解决问题,细心去改书中的例子,不断反复看运行结果,理解为什么会这样。 敲书中代码不要抄,要以逻辑的方式去记,就是理解为什么这么写,实在记不住了在去看一遍。不要想一两个月学会,不能心急,但也不要三天打鱼两天晒网,或听说java好又转java,看python好又去看python,任何语言都有各自的好,语言只是解决问题的工具,都是相通的,因为我初学时这都是我遇到的,希望对你有用。 明白为什么学,不轻易放弃。 c#学好后再去看别的语言都会很快学会,初学主要多培养多动手,然后再多想为什么,等c#图解啃完了,再看刘铁猛老师的视频你会豁然开朗,每个点讲的很深入。 之后就可以学习asp.net wpf 前端 算法 数据库 等等好玩的再后面呢。当然学c#无所谓framework还是core,但学到ASP.NET等框架时要学net core的。 wpf就net framework4.0以上就行,因为win7

快速回帖

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则