
简介《C#编程新手入门指南》以单份PDF电子书形式呈现对应《C#玩家指南》第三版内容面向零基础或刚接触.NET的编程学习者帮助其从语法入门逐步过渡到可独立完成小项目。全书按入门、基础、面向对象、高级主题与工具实践展开覆盖变量与类型系统、基本数学与用户输入、判断、switch、循环、数组、枚举、方法、值与引用类型并深入类与对象、继承、多态、泛型等核心概念后段还涉及文件、异常、线程及借助Visual Studio 2017和.NET平台提升开发效率的实用技巧。压缩包仅含1个PDF文件大小约9.27MB便于在电脑或平板上阅读也可按章节检索知识点。目前已有131人学习适合希望边读边练、系统建立C#知识框架的初学者作为入门读物。1. 零基础学 C#这门语言到底是个什么东西很多人第一次听到 C# 编程脑子里冒出来的是满屏看不懂的符号还没开始就先怯了三分。其实把它拆开看C# 就是一种给电脑下命令的语言你按它能读懂的格式写清楚先做什么、再做什么、什么情况下做什么它负责把这些话翻译成机器能执行的动作。它长在 .NET 这个平台上天生带一套现成的工具箱写窗口、读文件、连数据库都有零件可以直接拿。这份 C# 编程新手入门指南面向的正是完全没碰过代码的人从装软件、写下第一行输出开始一路走到面向对象编程、高级主题和调试技巧。所以先别急着背语法记住一件事就够了C# 是一门能边写边看结果的语言你今天敲下的每一行几分钟内就能在屏幕上跑起来。2. 为什么零基础也值得先学 C#三个能立刻感受到的好处2.1 语法规矩多但它几乎不跟你玩玄学刚入门的人最容易在两个极端里摇摆一种是觉得编程全靠天赋一种是觉得只要背完语法就万事大吉。C# 恰好站在中间偏讲道理的那一侧。它是一种强类型语言意思是你在声明一个变量时必须说清楚这个变量装的是整数、小数还是文字。听起来像是多了一道手续实际用起来反而是给新手省事类型对不上的地方编辑器当场就给你画红线根本轮不到程序跑起来再莫名其妙地崩掉。举个最常见的场景。你想把一段文字塞进一个只能装整数的变量里在很多松散的语言中这件事可能悄悄成功然后在几百行之外引发一个完全看不出原因的故障排查起来非常让人头疼。C# 不会这样它在编译阶段就直接拦住你告诉你哪个文件、哪一行、哪个类型不对。错误被提前暴露这是新手最需要的东西——你不需要有多年经验也能从提示里读出哦这里我放错东西了。这种设计还有一个隐性好处它逼着你养成先想清楚数据长什么样再动手写逻辑的习惯。很多人学编程卡住不是因为不会写循环而是因为脑子里对我要处理的东西究竟是什么一片模糊。C# 的类型系统像一个随身提醒每次声明变量都在问你一遍这个问题。等你把这套习惯带到别的语言里会发现思路清楚很多。所以别把语法规矩当成负担。它的作用类似自行车上的辅助轮刚开始觉得别扭骑顺了之后你根本感觉不到它的存在只会在快要摔倒时发现它其实救过你。2.2 一套工具走完全程Visual Studio 把编译、运行、调试收进一个窗口学编程最怕的不是难是碎。写代码用一个软件编译要敲命令运行要开终端出错要靠猜——四件事分散在四个地方新手的光是把流程走完就已经耗尽耐心。这份资源配套的主角是 Visual Studio它把这些环节收进了同一个窗口左边写代码上方点一下就能编译运行出问题时可以在某一行打个断点让程序跑到那里停下来你把鼠标悬在变量上就能看见它此刻的值。这个停下来看看的能力是新手和老手之间最明显的一道分水岭。没有它的时候程序出了错你只能靠打印语句一遍遍试像在黑屋子里摸开关。有了调试器你能亲眼看着数据一步步流动哪一步开始不对劲一目了然。书里专门用了两章讲这件事一章讲怎样充分利用 Visual Studio 的各种面板和快捷操作另一章讲怎样真正调试自己的代码。这两章被放在最后一部分很多读者一开始会跳过我建议反过来——早点看早点受益。对零基础的人来说工具选对能省掉大量无谓的消耗。你不需要先学会命令行编译、不需要手动管理一堆配置文件新建一个项目模板已经帮你把骨架搭好你只需要往里面填自己的那几行。等以后需要更精细的控制再去了解背后发生了什么也不迟。2.3 学完一段就有一段的用处从控制台到窗口程序的连续坡道很多编程入门材料有个通病前三分之二都在讲语法最后突然告诉你现在你已经学会了然后就没有然后了。学习者拿到的是一堆零散零件却不知道能拼成什么。这份指南的结构不是这样它的五大部分是一条连续的坡道每一段都有明确的落点。第一段是起步认识这门语言、装好工具、写出第一个程序、学会写注释。第二段是基础变量、类型系统、数学运算、接收用户输入、条件判断、循环、数组、方法。走到这里你已经能写出输入一批数字算平均值并判断是否及格这类小工具了。第三段是面向对象编程从创建自己的类讲到属性、继承、多态、接口、泛型中间还插了一个完整的井字棋项目——这是很多人第一次真切感受到代码可以组织得这么有条理的时刻。第四段是高级主题读写文件、错误处理与异常、委托与事件、Lambda 表达式、线程与异步编程。这一段不需要一次啃完可以当成工具箱遇到需要的时候回来翻。第五段讲工具和环境.NET 平台是什么、依赖和多个项目怎么管、常见编译错误怎么读、项目文件是怎么组织的。这一部分最容易被忽略却直接决定你从能写到能交付的距离。坡道的好处是你在任何一个位置停下手里都有能拿出手的东西。这比学完再说踏实得多。3. 第一次动手装好 Visual Studio跑通 Hello World3.1 安装这一步选哪个版本、勾哪些工作负载安装是整个入门路上第一个容易劝退的环节不是因为难而是因为选项太多。打开下载页面你会看到好几个版本名称里带社区、专业、企业之类的字样。对个人学习和练手来说选那个标注为个人可用的版本就够了功能上不缩水写代码、调试、跑项目该有的都有。安装器启动后会给出一长串工作负载复选框这一步比选版本重要得多。新手只需要盯住和 .NET 桌面开发相关的那一项勾上它C# 编译器、运行时、项目模板就都齐了。其余像游戏开发、移动开发、数据处理的选项现在勾了只会让安装包体积翻倍、装的时间拉长等以后真要用再回来加。安装过程通常要下载好几个 G慢是正常的。我见过有人装到一半以为卡死了直接关掉重来结果反复折腾一晚上。血泪经验是插上电源找个网速稳定的时间段让它自己跑完中间别去点取消。装完之后第一次启动会比较慢因为它在初始化各种缓存第二次就快了。提示如果你用的是 Mac 或者 Linux书里专门有一节讲这两种系统上怎么写 C#。核心概念和 Windows 上完全一致只是编辑器长得不一样碰到对不上的地方按概念去找对应功能就行。书里配套的是 Visual Studio 2017 那一代界面和现在的新版本有些差别但新建项目、编译、运行这几个关键动作的位置基本没变。照着做的时候如果发现按钮挪了位置先在顶部菜单里找文件和生成八成就在里面。3.2 新建项目项目、解决方案、程序集分别是什么这三个词是新手最早遇到的拦路虎它们听起来很像其实是三个层级。用一个装修的比方解决方案是整个工地项目是工地里的一间房子程序集是房子盖好之后交出来的成品。一个解决方案可以装好几个项目比如一个负责界面、一个负责数据处理每个项目单独编译产出一个程序集形态通常是可执行文件或者库文件。新建的时候你会先建一个解决方案通常编辑器会帮你顺手建好然后在里面加一个项目。项目类型选控制台应用这是最适合入门起步的形态——它没有界面所有交互都在一个黑底白字的窗口里用文字完成你可以把全部注意力放在逻辑本身不用分心去摆按钮、调布局。这里有个很多人踩过的坑一个解决方案里放了多个项目之后点运行却跑了另一个。原因是启动项目这个设置还停留在旧的那个上。解决办法是在解决方案资源管理器里右键你想跑的项目选设为启动项目标题栏会变成粗体提示你当前选的是谁。这个细节书里在讲依赖关系和多个项目的那一章有专门说明值得提前看一眼。至于项目文件是怎么组织的、编译产物放在哪个目录、配置文件长什么样这些内容在靠后的章节里讲。现在你不需要全部搞懂只需要知道一点你在编辑器里看到的那些文件最终会被编译成一个能双击运行的东西中间的过程工具帮你处理了。3.3 逐行拆 Hello World每一行到底在干嘛新建完控制台项目编辑器会直接给你一份能跑的代码。它很短但每一行都值得弄明白因为后面几百页的内容都是在这几行上长出来的。using System; // 引入 System 命名空间后面才能直接用 Console 这类工具 namespace HelloWorld // 命名空间相当于给这段代码挂一个门牌号避免重名 { class Program // 类C# 里所有代码都必须住在某个类里面 { static void Main(string[] args) // 程序的入口运行时从这里开始执行 { // 往控制台窗口输出一行文字写完自动换行 Console.WriteLine(Hello, World!); // 等待用户按回车防止窗口一闪就关掉 Console.ReadLine(); } } }第一行的using System;是取工具。C# 把功能按命名空间分组控制台输出这个能力放在 System 组里不写这一行下面就用不了 Console。你可以把它理解成我要用 System 这个抽屉里的东西先把它拉出来。namespace那一行是给代码编地址。想象两个项目里都有一个叫 Program 的类没有命名空间的话编译器就分不清谁是谁。日常写小练习时它不太起眼等你的项目变大、引用了别人的库这层隔离就变得很重要。class Program和里面的大括号是 C# 的硬性规定所有可执行代码都要放在某个类的方法里不能像某些脚本语言那样直接在文件顶层写语句。刚开始会觉得这是多余的包装等你学到面向对象那一部分就会明白类其实是这门语言组织代码的基本单位。static void Main(string[] args)是最关键的一行。它是整个程序的入口点运行程序时机器就是从这里开始一行一行往下走的。static表示它不需要创建对象就能调用void表示它跑完之后不返回结果括号里那个参数用来接收命令行传进来的内容——现在用不上先知道它在那儿就行。最后两行是实际动作Console.WriteLine往窗口打印一句话Console.ReadLine停下来等用户敲回车。后者经常被新手忽略结果就是程序跑完窗口立刻消失看起来像什么都没发生。3.4 编译和运行按下启动按钮之后发生了什么代码写完接下来是让它跑起来。顶部工具栏有两个长得差不多的按钮一个带绿色三角的启动一个是启动但不调试。快捷键上前者通常是 F5后者是 CtrlF5。对新手来说日常练习优先用带调试的那个因为程序出错时它能停下来告诉你哪儿出了问题而不调试直接启动跑得更快适合你已经确认没问题、只想看看输出的时候。按下按钮之后背后发生的事分三步。第一步是编译编译器把你写的 C# 代码翻译成中间语言这个过程中会检查语法、类型是否匹配发现问题就停下来在下方列出错误清单双击某一条能直接跳到出错的那一行。第二步是运行生成的可执行文件被启动运行时环境接管从 Main 方法开始执行。第三步是输出控制台窗口弹出来你写的文字出现在里面。编译这一步值得多说两句。新手最容易犯的错是漏掉行尾的分号或者把英文括号打成了中文括号。这类错误在编辑器里通常会有红色波浪线提示鼠标悬上去能看到原因。还有一种情况是代码看着完全正确但报错指向一个你根本没改过的地方——那多半是前面某一行少了右括号导致后面全乱了套。养成从报错行往上找的习惯比盯着报错那一行死看有效得多。另外补充一个和排版有关的小知识C# 里空格、换行、缩进这些空白字符对程序运行没有任何影响你把一行代码拆成三行写结果是一样的。但分号不能省它是语句结束的标志。这一点书里在第一个程序那一章就专门强调过因为它是新手编译失败的头号原因。4. 基础语法主线变量、类型、判断、循环怎么串起来学4.1 变量和类型系统给数据准备合适的盒子变量的概念一句话就能说清它是一个有名字的盒子你把数据放进去之后用名字就能取出来。C# 的要求是做盒子的时候必须说清楚这个盒子装什么——整数用一个型号小数用另一个型号。这就是类型。类型这么多新手先记住四个就够开工int装整数用来数数、记年龄、算数量double装小数用来算平均分、百分比bool只有真和假两个值用来做判断string装文字名字、提示语都靠它。剩下的一堆等真遇到需要节省内存或者处理金额精度的场景再回来看。类型装什么什么时候会用到int整数计数、年龄、循环次数double小数平均分、比例、坐标decimal高精度小数金额、价格别用 double 算钱bool真 / 假条件判断的结果string文字名字、提示语、一整段内容char单个字符代号、单个字母给变量起名也有讲究。a、b、c能跑但过两天你自己都看不懂。用有意义的名字比如studentCount、totalScore代码的可读性会立刻上一个台阶。书里在讲变量的那一章专门有一节叫好的变量名值得花五分钟读一遍这个习惯越早养成收益越大。关于数据在内存里怎么存、值类型和引用类型有什么区别这些内容在基础阶段可以先放着。它们是理解后面面向对象的关键但一上来就钻进去很容易在还没写过几行代码的时候就被概念淹掉。4.2 判断和循环让程序学会选择和重复到目前为止程序都是一行行往下执行的直线。判断和循环把这条直线变成了有分支、能折返的路径编程的威力从这里开始显现。判断用if。它的写法是把条件放在括号里条件成立就执行大括号里的内容。条件本身是一个 bool 值通常由比较运算符算出来比如age 18。多个条件可以用并且和||或者连起来!表示取反。if后面可以跟else处理条件不成立的情况再复杂的可以用else if一层层往下排。int score 76; // 假设这是某次考试的分数 if (score 90) // 第一个条件90 分及以上 { Console.WriteLine(优秀); } else if (score 60) // 上面不成立时才检查这里 { Console.WriteLine(及格); } else // 前面都不成立走这里 { Console.WriteLine(不及格); }执行顺序是从上往下逐个检查一旦某个条件成立执行完对应的大括号就直接跳出整个结构后面的不再看。这个特性很重要所以条件的顺序不能乱如果把score 60放到最前面那 95 分也会被判成及格。当判断的分支特别多、而且都是在比较同一个变量的不同取值时可以用switch写得更清爽。书里在讲 switch 的那一章还提到一个细节C# 不允许一个分支执行完自动滑到下一个分支必须显式写break这是它和某些语言不一样的地方也少了一类容易出错的隐患。循环用来重复。最常用的三种while是先判断再执行可能一次都不跑do-while是先执行一次再判断至少跑一次for把初始化、条件、更新三件事写在一行里适合次数明确的场景。// 从 1 数到 5 for (int i 1; i 5; i) { Console.WriteLine($第 {i} 次循环); // $ 开头表示字符串里可以直接嵌变量 }for括号里那三段用分号隔开分别是初始值i 1循环条件i 5每轮结束后的更新i意思是加一。执行流程是先初始化然后判断条件成立就跑循环体跑完执行更新再回去判断如此往复直到条件不成立为止。这个流程值得在纸上画一遍理解了它后面几乎所有循环相关的 bug 你都能自己定位。循环里还有两个开关break直接跳出整个循环continue跳过本轮剩下的部分直接进入下一轮。刚开始不用刻意记遇到需要的时候查一下就行。4.3 数组和方法把一堆数据和一段逻辑各自打包学到这儿你已经能用变量存单个值、用判断做选择、用循环做重复。但真实的问题往往涉及一批数据也往往需要把某段逻辑反复使用。数组和方法就是解决这两件事的工具。数组是一排连续的盒子用同一个名字加编号来访问。声明的时候要写明类型和长度索引从 0 开始这一点新手经常搞错。// 声明一个能装 5 个整数的数组 int[] scores new int[5]; scores[0] 88; // 第一个位置索引是 0 scores[1] 92; scores[2] 75; scores[3] 60; scores[4] 95; // 第五个位置索引是 4 // 遍历数组把每个分数打印出来 for (int i 0; i scores.Length; i) { Console.WriteLine(scores[i]); }注意循环条件写的是i scores.Length而不是。数组长度是 5合法索引是 0 到 4写成小于等于就会越界程序会直接抛异常。这个错误几乎每个新手都犯过而且因为它只在循环最后一轮才触发往往让人一愣。如果只是想把数组里的东西挨个看一遍用foreach更省事foreach (int s in scores)会自动把每个元素依次交给你不用担心索引越界。方法则是把一段逻辑打包起来起个名字之后调名字就能用。它的好处是重复利用和减少重复。当你发现自己在三个地方写了几乎一样的代码就该考虑把它抽成方法了。方法的定义包含返回类型、名字、参数列表用return把结果交出去如果只是做事不需要返回结果返回类型写void。数组和方法这两样东西是后面所有内容的地基。类是一组方法和数据的打包泛型是对类型做的抽象委托是把方法本身当成值来传递——全都建立在你已经会用方法这个前提上。4.4 串起来跑一个输入名字年龄算出明年的年龄把前面的零件拼起来写一个真正能交互的小程序。它的流程是问名字、问年龄、计算、输出。using System; class Program { static void Main() { // 提示用户输入名字ReadLine 读回来的永远是字符串 Console.Write(请输入你的名字); string name Console.ReadLine(); // 提示用户输入年龄读回来的仍然是字符串 Console.Write(请输入你的年龄); string ageText Console.ReadLine(); // 把字符串转换成整数这一步不能省 int age int.Parse(ageText); // 整数加法算出明年的年龄 int nextYearAge age 1; // 用加号把文字和变量拼起来输出 Console.WriteLine(你好 name 明年你就 nextYearAge 岁了。); } }几个地方值得展开说。Console.Write和Console.WriteLine的区别只在于一个不换行、一个换行用在提示语上前者能让用户的光标停在冒号后面体验更自然。Console.ReadLine()的返回值类型固定是字符串哪怕用户输入的是 100你拿到的也是100这三个字符不是数字一百。所以必须用int.Parse转一次这一步是新手最容易忘记的忘了就会在拼接输出时得到明年你就 1001 岁这种结果——因为字符串加整数变成了拼接。int.Parse有一个明确的软肋如果用户输入的不是数字比如打了一个二十程序会直接抛异常退出。在练习阶段这没关系先跑通再说但这也是最典型的翻车现场后面讲避坑的时候会给出更稳的写法。最后那句输出用的是加号拼接。当内容变长这种写法会变得很难读所以 C# 提供了字符串插值在字符串前面加一个$然后把变量用大括号包起来放进去效果一样但清楚得多。上面那个循环里的$第 {i} 次循环就是这个用法。5. 新手避坑五个几乎人人都会遇到的错误5.1 程序一闪就没了看起来像什么都没发生现象按下运行黑色的控制台窗口弹出来一瞬间又消失了你甚至没看清里面写了什么。原因程序从 Main 方法第一行跑到最后一行执行完就结束了窗口随之关闭。如果你写的是一个没有暂停的程序它跑完的时间可能只有几毫秒肉眼根本来不及捕捉。解决在 Main 方法的最后加一句Console.ReadLine();让程序停下来等用户敲回车。如果你用的是带调试的方式启动程序结束后窗口通常不会立刻关闭或者会提示按任意键继续所以这类问题在调试模式下反而不容易出现这也解释了为什么有人换一种启动方式就好了。5.2 代码看着没错编译却死活不通过现象明明照着书写的一模一样编译器却报错红色波浪线出现在一些看起来毫不相干的地方。原因八成是两个隐形问题之一。一是标点符号用了中文输入法打出来的全角字符比如中文分号、中文括号它们在屏幕上和英文符号几乎一样但编译器完全不认。二是大小写没对上C# 是严格区分大小写的console和Console是两个不同的东西。解决把输入法切到英文状态再检查一遍报错行附近的符号。如果报错位置看起来没问题往上找几行很可能是前面漏了一个右括号或者右花括号导致后面的结构全部错位。养成写完一段就编译一次的习惯比写完几百行再一起排查轻松得多。5.3 用户输入不是数字程序直接崩了现象程序正常跑起来输入数字一切正常但只要手滑输入了字母或者直接回车程序立刻抛出一堆红色文字然后退出。原因int.Parse的职责只有一个——把合法的数字字符串转成整数。它不接受任何不合法的情况一旦遇到就抛异常。而用户永远会输入你没预料到的东西这是躲不掉的现实。解决换成int.TryParse它不会抛异常而是返回一个 bool 告诉你转换成不成功转换结果通过out参数带出来。// 先声明变量TryParse 成功后会把结果写进 age int age; bool ok int.TryParse(ageText, out age); if (ok) { Console.WriteLine(你的年龄是 age); } else { // 转换失败时 age 会被置为 0但程序不会崩 Console.WriteLine(输入的不是数字请重新运行再试一次。); }区别只有一点一个是必须成功否则大家都别玩一个是先试试不行我给你个信号。凡是涉及外部输入的地方后者基本都是更稳妥的选择。5.4 除法算出来的结果总是整数现象算平均分或者比例的时候明明应该是 2.5、3.75结果屏幕上显示的是 2 或者 3小数部分凭空消失了。原因两个整数相除C# 会执行整数除法结果自动截断成整数不是四舍五入是直接砍掉小数部分。5 / 2得到 21 / 3得到 0。这个规则本身没问题问题出在很多人在写的时候没意识到两边的类型都是整数。解决让参与运算的两个数里至少有一个是小数类型。最简单的做法是在字面量后面加个.0或者把其中一个变量声明成double。int total 5; int count 2; Console.WriteLine(total / count); // 输出 2整数除法 Console.WriteLine(total / (double)count); // 输出 2.5强制转成小数再除括号里那个(double)是类型转换意思是把这个值临时当成 double 来用。记住一条经验只要涉及除法又希望得到小数就提前把类型处理好别等结果不对了再回来查。5.5 改了代码运行结果还是老的现象明明改了输出内容运行起来却还是显示旧的结果反复确认代码确实存盘了。原因常见的有两种情况。一种是改了文件但没保存编辑器标题栏上那个小圆点就是未保存的标记编译的是硬盘上的旧版本。另一种更隐蔽一个解决方案里放了多个项目启动项目还停在上一个所以你运行的根本不是你以为的那份代码。解决先按 CtrlS 保存看标题栏的小圆点是否消失还不对就去解决方案资源管理器里确认启动项目右键目标项目选设为启动项目粗体那个才是当前会跑的。再不行就清理一次解决方案重新生成把旧的编译产物删掉重来。这类问题排查起来没有任何技术含量但卡住的人非常多因为它违背直觉——你会一直以为自己代码写错了。6. 学完基础往哪走从面向对象到 .NET 的爬坡路线6.1 三个阶段别跳着走基础语法跑通之后很多人会迫不及待地去找高级内容看结果被一堆概念砸懵回头怀疑自己不适合这行。更稳的做法是分三段走每段都有明确的判断标准。阶段主要内容走完的标志第一段面向对象编程创建自己的类、属性、继承、多态、接口、泛型能自己设计两三个类并把它们组合起来完成一个小功能第二段高级主题文件读写、异常处理、委托与事件、Lambda、线程与异步能写出读写文件、出错不崩、界面不卡的程序第三段工具与环境.NET 平台、多项目依赖、常见编译错误、调试、项目文件组织能独立新建工程、定位报错、配置引用第一段是分水岭。在这之前你的代码是一堆按顺序执行的语句在这之后你开始用对象来建模问题。井字棋那个小项目就是很好的练习它需要棋盘、玩家、判断胜负这几块拼在一起逼着你思考类该怎么划分。这一关过了后面就顺了。第二段不用一次啃完。文件读写和异常处理用得上就先学委托和异步可以等遇到实际问题再回来翻。第三段最容易被跳过但它决定了你从能写到能交付的距离尤其是调试那一章我建议在第一段结束之后就回头补上。6.2 每天二十分钟的练习习惯有个很实在的建议每天写二十分钟但不要追求写完一个大项目。具体做法是把书里每一章的示例代码亲手敲一遍敲完立刻改一处——把输出文字换掉把判断条件的数字调大把循环次数改成用户输入。改完跑一遍观察结果怎么变。这个动作看着幼稚效果却出奇地好。因为照着抄只是手指在动改动才逼你去理解每一行在起什么作用。我第一次学的时候图省事整章整章地复制粘贴看着都能跑一到自己写就一片空白那种感觉非常打击人。后来改成手动敲、随手改进度慢了但再也没出现过看着会、写不出的情况。还有一条把遇到的每一个报错记下来写清楚现象、原因、怎么解决的。三个月之后你会积累出一份属于自己的错题本它比任何教程都贴合你的薄弱点。从那以后我每跑一个新项目都会先确认启动项目是哪一个、有没有未保存的文件再按运行——这个小习惯帮我省掉了无数个代码明明改了为什么没生效的下午。希望这些能帮到你。本文还有配套的精品资源点击获取