.NET中异常处理的最佳实践(译)

原文地址:点击打开链接

本文翻译自CodeProject上的一篇文章,原文地址。

目录

介绍

做最坏的打算

提前检查

不要信任外部数据

可信任的设备:摄像头、鼠标以及键盘

 “写操作”同样可能失效

安全编程

不要抛出“new Exception()”

不要将重要的异常信息存储在Message属性中

每个线程要包含一个try/catch块

捕获异常后要记录下来

不要只记录Exception.Message的值,还需要记录Exception.ToString()

要捕获具体的异常

不要中止异常上抛

清理代码要放在finally块中

不要忘记使用using

不要使用特殊返回值去表示方法中发生的异常

不要使用“抛出异常”的方式去表示资源不存在

不要将“抛出异常”作为函数执行结果的一种

可以使用“抛出异常”的方式去着重说明不能被忽略的错误

不要清空了堆栈跟踪(stack trace)信息

异常类应标记为Serializable

使用”抛出异常”代替Debug.Assert

每个异常类至少包含三个构造方法

不要重复造轮子

VB.NET

模拟C#中的using语句

不要使用非结构化异常处理(On Error goto)

总结

介绍

“我的软件程序从来都不会出错”。你们相信吗?我几乎可以肯定所有人都会大喊我是个骗子。“软件程序几乎不可能没有bug!”

事实上,开发一个可信任、健全的软件程序并不是不可能的事情。注意我这里并不是指那些用于控制核电站的软件,而是指一些常见的商业软件,这些软件可能运行在服务器上,又或者PC机上,它们可以连续工作几个星期甚至几个月都不会出现重大问题。可以猜到,我刚才的意思是指软件有一个比较低的出错率,你可以迅速找到出错的原因并快速修复,并且出现的错误并不会造成重大的数据损坏。

换句话说,我的意思是指软件比较稳定。

软件中有bug是可以理解的。但是如果是经常出现的bug,并且因为没有足够的提示信息导致你不能迅速修复它,那么这种情况是不可被原谅的。

为了更好地理解我上面所说的话,我举个例子:我经常看见无数的商业软件在遇到硬盘不足时给出这样的错误提示:

“更新客户资料失败,请与系统管理员联系然后重试”。

除了这些外,其他任何信息都没有被记录。要搞清楚到底什么原因引起的这个错误是一件非常耗时的过程,在真正找到问题原因之前,程序员可能需要做各种各样的猜测。

注意在这篇文章中,我主要讲怎样更好地处理.NET编程中的异常,并没有打算讨论怎样显示合适的“错误提示信息”,因为我觉得这个工作属于UI界面开发者,并且它大部分依赖于UI界面类型以及最终使用软件的用户。比如一个面向普通用户的文本编辑器的“错误提示信息”应该完全不同于一个Socket通信框架,因为后者直接用户是程序员。

 

做最坏的打算

遵守一些基本的设计原则可以让你的程序更加健全,并且当错误发生时,能够提升用户体验。我这里说到的“提升用户体验”并不是指错误的提示窗体能够让用户高兴,而是指发生的错误不会损坏原有数据,不会让整个电脑崩溃。如果你的程序遇到硬盘不足的错误,但是程序不会造成其他任何负面效果(仅仅提示错误信息,不会引起其他问题,译者注),那么这时候就提升了用户体验。

提前检查

强类型检查和验证是避免bug发生的有力方法。你越早发现问题,就越早修复问题。几个月后再想搞清楚“为什么InvoiceItems表中的ProductID栏会存在一个CustomerID数据?”是一件不太容易并且相当恼火的事情。如果你使用一个类代替基本类型(如int、string)去存储客户(Customer)的数据的话,编译器就不会允许刚才那件事情(指将CustomerID和ProductID混淆,译者注)发生。

不要信任外部数据

外部数据是不可靠的,我们的软件程序在使用它们之前必须严格检查。无论这些外部数据来自于注册表、数据库、硬盘、socket还是你用键盘编写的文件,所有这些外部数据在使用前必须严格进行检查。很多时候,我看到一些程序完全信任配置文件,因为开发这些程序的程序员总是认为没有人会编辑配置文件并损坏它。

可信任的设备:摄像头、鼠标以及键盘

当你需要用到外部数据时,你可能会遇到以下情况:

  1)没有足够的安全权限

  2)数据不存在

  3)数据不完整

  4)数据完整,但是格式不对

不管数据源是注册表中的某个键、一个文件、socket套接字、数据库、Web服务或者串口,以上情况均可能发生。所有的外部数据总会有失效的可能。

“写操作”同样可能失效

不可信任的数据源同样也是一种不可信任的数据仓库。当你存储数据时,相似情况依旧可能会发生:

  1)没有足够的安全权限

  2)设备不存在

  3)没有足够的空间

  4)存储设备发生了物理错误

这就是为什么一些压缩软件在工作时创建了一个临时文件,当工作完成后再重命名,而不是直接修改源文件。原因是如果硬盘损坏(或者软件异常)可能导致原始数据丢失。(译者遇见过这种情况,备份数据时断电,结果原来的旧版备份被损坏了,译者注)

 

安全编程

我的一个朋友告诉我:一个好的程序员从来不会在他的程序中编写糟糕的代码。我觉得这只是成为一个好程序员的必要条件而不是充分条件。下面我整理了一些当你进行异常处理时,可能会编写的“糟糕代码”:

不要抛出“new Exception()”

请别这样做。Exception是一个非常抽象的异常类,捕获这类异常通常会产生很多负面影响。通常情况下应该定义我们自己的异常类,并且需要区分系统(framework)抛出的异常和我们自己抛出的异常。

不要将重要的异常信息存储在Message属性中

异常都封装在类中。当你需要返回异常信息时,请将信息存储在一些单独的属性中(而不要放在Message属性中),否则人们很难从Message属性中解析出他们需要的信息。比如当你仅仅需要纠正一下拼写错误,如果你将错误信息和其它提示内容一起以String的形式写在了Message属性中,那么别人该怎样简单地获取他们要的错误信息呢?你很难想象到他们要做多少努力。

每个线程要包含一个try/catch块

一般异常处理都放在了程序中一个比较集中的地方。每个线程都需要有一个try/catch块,否则你会漏掉某些异常从而出现难以理解的问题。当一个程序开启了多个线程去处理后台任务时,通常你会创建一个类型来存储各个线程执行的结果。这时候请不要忘记了为类型增加一个字段来存储每个线程可能发生的异常,否则的话,主线程不会知道其他线程的异常情况。在一些“即发即忘”的场合(意思主线程开启线程后不再关心线程的运行情况,译者注),你可能需要将主线程中的异常处理逻辑复制一份到你的子线程中去。

捕获异常后要记录下来

不管你的程序是使用何种方式记录日志——log4net、EIF、Event Log、TraceListeners或者文本文件等,这些都不重要。重要的是:当你遇到异常后,应该在某个地方将它记录在日志中。但是请仅仅记录一次,否则的话,你最后会得到一个非常大的日志文件,包含了许多重复信息。

不要只记录Exception.Message的值,还需要记录Exception.ToString()

当我们谈到记录日志时,不要忘了我们应该记录Exception.ToString()的值,而不是Exception.Message。因为Exception.ToString()包含了“堆栈跟踪”(stack trace)信息,内部异常信息以及Message。通常这些信息非常重要,而如果你只记录Exception.Message的话,你只可能看到类似“对象引用未指向堆中实例”这样的提示。

要捕获具体的异常

如果你要捕获异常,请尽可能的捕获具体异常(而非Exception)。

我经常看见初学者说,一段好的代码就是不能抛出异常的代码。其实这说法是错误的,好的代码在必要时应该抛出相应的异常,并且好的代码只能捕获它知道该怎么处理的异常(注意这句话,译者注)。

下面的代码作为对这条规则的说明。我敢打赌编写下面这段代码的那个家伙看见了会杀了我的,但是它确实是摘取自真实编程工作中的一段代码。

第一个类MyClass在一个程序集中,第二个类GenericLibrary在另一个程序集中。在开发的机器上运行正常,但是在测试机器上却总是抛出“数据不合法!”的异常,尽管每次输入的数据都是合法的。

你们能说说这是为什么吗?

public class MyClass{    public static string ValidateNumber(string userInput)    {        try        {            int val = GenericLibrary.ConvertToInt(userInput);            return "Valid number";        }        catch (Exception)        {            return "Invalid number";        }    }}public class GenericLibrary{    public static int ConvertToInt(string userInput)    {        return Convert.ToInt32(userInput);    }}

这个问题的原因就是异常处理不太具体。根据MSDN上的介绍,Convert.ToInt32方法仅仅会抛出ArgumentException、FormatException以及OverflowException三个异常。所以,我们应该仅仅处理这三个异常。

问题发生在我们程序安装的步骤上,我们没有将第二个程序集(GenericLibrary.dll)打包进去。所以程序运行后,ConvertToInt方法会抛出FileNotFoundException异常,但是我们捕获的异常是Exception,所以会提示“数据不合法”。

不要中止异常上抛

最坏的情况是,你编写catch(Exception)这样的代码,并且在catch块中啥也不干。请不要这样做。

清理代码要放在finally块中

大多数时候,我们只处理某一些特定的异常,其它异常不负责处理。那么我们的代码中就应该多一些finally块(就算发生了不处理的异常,也可以在finally块中做一些事情,译者注),比如清理资源的代码、关闭流或者回复状态等。请把这当作习惯。

有一件大家容易忽略的事情是:怎样让我们的try/catch块同时具备易读性和健壮性。举个例子,假设你需要从一个临时文件中读取数据并且返回一个字符串。无论什么情况发生,我们都得删除这个临时文件,因为它是临时性的。

让我们先看看最简单的不使用try/catch块的代码:

string ReadTempFile(string FileName){    string fileContents;    using (StreamReader sr = new StreamReader(FileName))    {        fileContents = sr.ReadToEnd();    }    File.Delete(FileName);    return fileContents;}

这段代码有一个问题,ReadToEnd方法有可能抛出异常,那么临时文件就无法删除了。所以有些人修改代码为:

string ReadTempFile(string FileName){    try    {        string fileContents;        using (StreamReader sr = new StreamReader(FileName))        {            fileContents = sr.ReadToEnd();        }        File.Delete(FileName);        return fileContents;    }    catch (Exception)    {        File.Delete(FileName);        throw;    }}

这段代码变得复杂一些,并且它包含了重复性的代码。

那么现在让我们看看更简介更健壮的使用try/finally的方式:

string ReadTempFile(string FileName){    try    {        string fileContents;        using (StreamReader sr = new StreamReader(FileName))        {            fileContents = sr.ReadToEnd();        }        File.Delete(FileName);        return fileContents;    }    catch (Exception)    {        File.Delete(FileName);        throw;    }}

变量fileContents去哪里了?它不再需要了,因为返回点在清理代码前面。这是让代码在方法返回后才执行的好处:你可以清理那些返回语句需要用到的资源(方法返回时需要用到的资源,所以资源只能在方法返回后才能释放,译者注)。

不要忘记使用using

仅仅调用对象的Dispose()方法是不够的。即使异常发生时,using关键字也能够防止资源泄漏。(关于对象的Dispose()方法的用法,可以关注我的书,有一章专门介绍。译者注)

不要使用特殊返回值去表示方法中发生的异常

因为这样做有很多问题:

  1)直接抛出异常更快,因为使用特殊的返回值表示异常时,我们每次调用完方法时,都需要去检查返回结果,并且这至少要多占用一个寄存器。降低代码运行速度。

  2)特殊返回值能,并且很可能被忽略

  3)特殊返回值不能包含堆栈跟踪(stack trace)信息,不能返回异常的详细信息

  4)很多时候,不存在一个特殊值去表示方法中发生的异常,比如,除数为零的情况:

public int pide(int x, int y){    return x / y;}

不要使用“抛出异常”的方式去表示资源不存在

微软建议在某些特定场合,方法可以通过返回一些特定值来表示方法在执行过程中发生了预计之外的事情。我知道我上面提到的规则恰恰跟这条建议相反,我也不喜欢这样搞。但是一些API确实使用了某些特殊返回值来表示方法中的异常,并且工作得很好,所以我还是觉得你们可以谨慎地遵循这条建议。

我看到了.NET Framework中很多获取资源的API方法使用了特殊返回值,比如Assembly.GetManifestStream方法,当找不到资源时(异常),它会返回null(不会抛出异常)。

不要将“抛出异常”作为函数执行结果的一种

这是一个非常糟糕的设计。代码中包含太多的try/catch块会使代码难以理解,恰当的设计完全可以满足一个方法返回各种不同的执行结果(绝不可能到了必须使用抛出异常的方式才能说明方法执行结果的地步,译者注),如果你确实需要通过抛出异常来表示方法的执行结果,那只能说明你这个方法做了太多事情,必须进行拆分。(这里原文的意思是,除非确实有异常发生,否则一个方法不应该仅仅是为了说明执行结果而抛出异常,也就是说,不能无病呻呤,译者注)

可以使用“抛出异常”的方式去着重说明不能被忽略的错误

我可以举个现实中的例子。我为我的Grivo(我的一个产品)开发了一个用来登录的API(Login),如果用户登录失败,或者用户并没有调用Login方法,那么他们调用其他方法时都会失败。我在设计Login方法的时候这样做的:如果用户登录失败,它会抛出一个异常,而并不是简单的返回false。正因为这样,调用者(用户)才不会忽略(他还没登录)这个事实。

不要清空了堆栈跟踪(stack trace)信息

堆栈跟踪信息是异常发生时最重要的信息,我们经常需要在catch块中处理一些异常,有时候还需要重新上抛异常(re-throw)。下面来看看两种方法(一种错误的一种正确的):

错误的做法:

try{    // Some code that throws an exception}catch (Exception ex){    // some code that handles the exception    throw ex;}

为什么错了?因为当我们检查堆栈跟踪信息时,异常错误源变成了“thorw ex;”,这隐藏了真正异常抛出的位置。试一下下面这种做法:

try{    // Some code that throws an exception}catch (Exception ex){    // some code that handles the exception    throw;}

有什么变化没?我们使用“throw;”代替了“throw ex;”,后者会清空原来的堆栈跟踪信息。如果我们在抛出异常时没有指定具体的异常(简单的throw),那么它会默认地将原来捕获的异常继续上抛。这样的话,上层代码捕获的异常还是最开始我们通过catch捕获的同一个异常。

拓展阅读:

C# 异常处理(Catch Throw)IL分析

异常类应标记为Serializable

很多时候,我们的异常需要能被序列化。当我们派生一个新的异常类型时,请不要忘了给它加上Serializable属性。谁会知道我们的异常类会不会用在Remoting Call或者Web Services中呢?

使用”抛出异常”代替Debug.Assert

当我们发布程序后,不要忘了Debug.Assert将会被忽略。我们在代码中做一些检查或者验证工作时,最好使用抛出异常的方式代替输出Debug信息。

  将输出Debug信息这种方式用到单元测试或者那些只需要测试当软件真正发布后确保不会出错的场合。

每个异常类至少包含三个构造方法

做这件事相当简单(直接从其他的类型粘贴拷贝相同的代码即可),如果你不这样做,那么别人在使用你编写的异常类型时,很难遵守上面给出的一些规则的。

  我指的哪些构造方法呢?这三个构造方法可以参见这里。

 

不要重复造轮子

已经有很多在异常处理方面做得比较好的框架或库,微软提供的有两个:

Exception Management Application Block

Microsoft Enterprise Instrumentation Framework

注意,如果你不遵守我上面提到的一些规则,这些库对你来讲可能没什么用。

 

VB.NET

如果你已经读完整篇文章,你就会发现所有的示例代码都是用C#编写的。那是因为C#是我比较喜欢的.NET语言,并且VB.NET有它自己的一些特殊规则。

模拟C#中的using语句

不幸的是,VB.NET中并没有using语句。你每次在释放一个对象的非托管资源时,不得不这样去做:

.NET中异常处理的最佳实践(译)

如果你不按照上面那种方式调用DIspose方法的话,很可能会出现错误(有关Dispose方法的调用,请关注新书。译者注)。

不要使用非结构化异常处理(On Error Goto)

非结构化异常处理也叫“On Error Goto”,Djikstra(艾兹赫尔·戴克斯特拉)在1974年说过“goto语句有害无益”,这已经是30年之前了!请删除你代码中的所有goto式的语句,我向你保证,他们万害无一益。(艾兹赫尔·戴克斯特拉提出了“goto有害论”、信号量和PV原语,解决了有趣的哲学家就餐问题。《软件故事》一书中讲Fortran语言时提到过他。译者注)

 

总结

我希望本篇文章能够让一部分人能够提高他们的编码质量,也希望这篇文章是讨论怎样有效地进行异常处理的开始,并让我们编写的程序更加健壮。

 

译者话:

我有一个缺点,不知道有没有网友跟我一样。我是个慢热型的人,对技术也一样,好多东西流行颠峰时期过去了我才开始有所感觉。主要一是因为我对新鲜东西不太感冒;二是我总感觉原来学习的东西还没有掌握好就换,有点半途而废的意思。其实我也知道这样非常不好,毕竟IT行业是个快速发展的行业,一没跟上步伐就落后了。

.NET中异常处理的最佳实践(译)

正是遇见这样相互矛盾的情况,我在学习知识的时候都是重点学习技术间的通性,所谓通性,即十年、二十年甚至三十年不太会变、不太会没落的东西,如果你现在从事的公司实际开发过程中一直使用某一套框架,你要是死抓着“怎样使用这个框架做出好的系统”不放,那么过几年你可能就落伍了。而如果你研究研究编程中的共性,比如协议、系统间的交互原理等,这些在每个网络通信系统中都会用到,无论是貌似已经过时了的PC程序,还是Web程序,还是当前流行的移动APP,都会用到,而且基本原理都是一样的。看得多了,就发现新东西出来好像是换汤不换药的感觉(稍微夸张:-))

因此,我给那些跟我一样,不太跟随新鲜事物的人、或者那些长期从事某一类固定开发工作的人的建议是:找准技术间的共性,不要停留在技术表面,除非你对新鲜事物足够感兴趣,并且有充分精力。

以上这些话也是我们公司开讨论会时分享的。

作者:周见智
出处:http://www.php.cn/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。 

补充:

关于CLR的 “两轮遍历”异常处理策略。
当应用 程序拥有多层嵌套的异常捕获结构时,如果最底层(其实在中间层也一样)发生了异常,CLR将优先在引发异常的那一层去搜索catch语句块,看看有没有“兼容”
此类型异常的处理代码 ,如果没有,就“跳到”上一层去搜索,如果上一层还没有,继续搜索上一层的“上一层”,由此直到应用 程序的最顶层。
这就是CLR处理嵌套异常捕获结构应用程序的“第一轮”遍历—–查找合适的异常处理程序。
如果在某一层找到了异常处理程序,注意,CLR并不会马上执行之,而是回到”事故现场”,再次进行“第二轮”遍历,执行所有“中间”层次的finally 语句块,然后,执行
找到异常处理程序 ,最后,再从本层开始一直遍历到最顶层,执行所有的finally语句块。

 以上就是.NET中异常处理的最佳实践(译)的内容,更多相关内容请关注PHP中文网(www.php.cn)! 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1432317.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年12月17日 06:28:39
下一篇 2025年12月17日 06:28:54

相关推荐

  • 最优的Yii框架中CSS引用实践

    Yii框架中引用CSS的最佳实践,需要具体代码示例 在Web开发中,引用CSS对于页面的样式定义至关重要。而在Yii框架中,我们可以灵活地引用CSS文件来实现页面的样式定制。本文将介绍Yii框架中引用CSS的最佳实践,并提供具体的代码示例。 使用Assets管理静态资源 Yii框架提供了Assets…

    2025年12月24日
    000
  • 网页加载速度的最佳实践:优化重排、重绘和回流

    提升网页加载速度:重排、重绘和回流的最佳实践,需要具体代码示例 随着互联网的快速发展,网页加载速度已经成为了用户体验中至关重要的一环。没有人愿意等待漫长的加载时间,因此如何提高网页加载速度成为了一个非常关键的问题。 网页的加载速度受到多种因素的影响,其中重排、重绘和回流是三个主要的性能瓶颈。本文将介…

    2025年12月24日
    000
  • CSS布局指南:实现网格布局的最佳实践

    CSS布局指南:实现网格布局的最佳实践 引言:在现代网页设计中,网格布局已经成为一种非常流行的布局方式。它可以帮助我们更好地组织页面结构,使其更具有层次感和可读性。本篇文章将介绍网格布局的最佳实践,以及具体的代码示例,帮助你更好地实现网格布局。 一、什么是网格布局?网格布局是指通过网格将页面分成多个…

    2025年12月24日
    000
  • CSS布局技巧:实现全屏背景图片的最佳实践

    CSS布局技巧:实现全屏背景图片的最佳实践 在网页设计中,全屏背景图片是一种常见的技巧,可以为网页增添视觉上的冲击力和吸引力。在CSS中,有几种方法可以实现全屏背景图片,本文将介绍其中的最佳实践,并提供具体的代码示例。 使用background-size属性 background-size属性可以控…

    2025年12月24日
    000
  • CSS布局技巧:实现卡片翻页效果的最佳实践

    CSS布局技巧:实现卡片翻页效果的最佳实践 引言:在现代Web设计中,实现卡片翻页效果已成为一种流行的布局方式。通过使用CSS,我们可以轻松地为网页添加动态、交互性和吸引力。本文将介绍如何使用最佳实践来实现卡片翻页效果,并提供一些具体的代码示例。 一、卡片布局基础在开始编写代码之前,让我们先来了解一…

    2025年12月24日
    000
  • CSS网页布局技巧:实现分栏和侧边栏的最佳实践

    CSS网页布局技巧:实现分栏和侧边栏的最佳实践 在开发网页时,一个常见的需求是实现分栏和侧边栏的布局。这种布局可以将页面内容划分为主要内容区域和边栏区域,使网页结构更清晰,提高用户体验。在本文中,我们将介绍一些实现分栏和侧边栏布局的最佳实践,并提供具体的代码示例。 一、使用CSS Grid布局 CS…

    2025年12月24日
    000
  • CSS布局技巧:实现屏幕折叠效果的最佳实践

    CSS布局技巧:实现屏幕折叠效果的最佳实践 随着移动设备的普及和屏幕尺寸的多样化,响应式设计已经成为了网页开发中的一项重要任务。其中一个关键方面就是实现屏幕折叠效果,即在较小的屏幕上折叠网页内容以适应屏幕空间的限制。本文将介绍一些最佳实践,以及具体的CSS代码示例来帮助开发者实现优雅的屏幕折叠效果。…

    2025年12月24日
    000
  • CSS布局技巧:实现堆叠卡片效果的最佳实践

    CSS布局技巧:实现堆叠卡片效果的最佳实践 在现代网页设计中,卡片式布局成为了一种非常流行的设计趋势。卡片布局能够有效地展示信息,提供良好的用户体验,并且方便响应式设计。在这篇文章中,我们将分享一些实现堆叠卡片效果的最佳CSS布局技巧,同时提供具体的代码示例。 使用Flexbox布局 Flexbox…

    2025年12月24日
    000
  • CSS布局技巧:实现圆形导航菜单的最佳实践

    CSS布局技巧:实现圆形导航菜单的最佳实践 在现代网页设计中,导航菜单是一个很重要的元素。为了提升用户体验和视觉吸引力,许多设计师选择使用圆形导航菜单。本文将介绍如何使用CSS实现圆形导航菜单的最佳实践,并提供具体的代码示例。 使用HTML创建导航菜单的基本结构 首先,我们需要使用HTML创建导航菜…

    2025年12月24日
    000
  • jimdo怎么插入html5时间轴_jimdo时间轴html5代码与节点样式【实操】

    Jimdo网站需用自定义HTML5代码实现时间轴:一、内联HTML+CSS轻量嵌入;二、外链CSS+语义化HTML便于复用;三、调用timeline-js-lite库支持交互;四、纯CSS方案零依赖高性能。 如果您希望在 Jimdo 网站中呈现可视化的时间发展脉络,但默认编辑器不支持原生时间轴组件,…

    2025年12月23日
    000
  • visual怎么创建html5_VS新建HTML File选HTML5模板快速创建页面【创建】

    可在Visual Studio中通过新建文件选HTML5模板、新建ASP.NET Core Web App项目或手动创建.html文件并输入及html:5代码段三种方式快速生成HTML5网页。 如果您在 Visual Studio 中需要快速创建一个符合 HTML5 标准的网页文件,则可通过新建项目…

    2025年12月23日
    000
  • jimdo怎么插入html5粒子效果_jimdo粒子效果html5库引入与参数调整【攻略】

    可在Jimdo通过自定义HTML区块引入tsparticles库实现动态粒子效果,或用内联SVG替代;需调整颜色、数量等参数适配主题,并修复脚本加载问题。 如果您希望在 Jimdo 网站中添加动态 HTML5 粒子效果(如背景浮动粒子、鼠标交互连线等),但发现 Jimdo 编辑器默认不支持直接嵌入 …

    2025年12月23日
    000
  • vs.net怎么运行html_vs.net运行html步骤【指南】

    首先创建Web项目或配置外部浏览器预览HTML文件。通过新建ASP.NET项目并添加HTML页面后按Ctrl+F5运行,或安装Live Server等插件实现静态文件实时预览,也可在选项中设置Chrome等外部浏览器直接打开HTML文件以查看效果。 如果您在使用 Visual Studio .NET…

    2025年12月23日
    000
  • vs中如何添加html_VS开发工具中添加HTML文件【工具】

    在 Visual Studio 中添加 HTML 文件需根据项目类型选择方法:一、通过解决方案资源管理器→添加新项→选“HTML 页面”模板;二、手动创建.html文件后通过“显示所有文件”→“包括在项目中”;三、用快捷键Shift+Alt+A快速调出模板;四、若无模板,需通过 Visual Stu…

    2025年12月23日
    000
  • HTML如何弹出提示框_JavaScript交互实现方法【指南】

    JavaScript提供五种弹出提示框方法:alert()显示不可编辑警告;confirm()返回布尔值实现确认交互;prompt()获取用户文本输入;自定义DOM元素实现灵活样式;第三方库如SweetAlert2支持美观异步提示。 如果您希望在网页中向用户显示简短信息、确认操作或获取简单输入,Ja…

    2025年12月23日
    000
  • vs怎么编写并运行html_vs编写并运行html方法【教程】

    Visual Studio中运行HTML的方法包括:1. 创建ASP.NET项目,添加HTML文件并设为起始页,通过IIS Express运行;2. 使用VS Code安装Live Server扩展实现实时预览;3. 直接保存HTML文件后用浏览器手动打开查看效果。 如果您在使用 Visual St…

    2025年12月23日
    000
  • vs如何写html_vs编写html步骤【教程】

    在Visual Studio中编写HTML需依次创建ASP.NET Core Empty项目、添加index.html文件、编辑保存内容、用浏览器预览,并可安装Live Server扩展实现保存即刷新。 如果您希望在 Visual Studio 中编写 HTML 文件,但不确定如何创建项目、添加文件…

    2025年12月23日
    000
  • visal stdio怎么运行html_visual studio运行html步骤【指南】

    首先安装“ASP.NET和Web开发”工作负载,创建或打开项目后添加HTML文件,编写代码并设为起始页,最后按Ctrl+F5通过IIS Express运行,可在浏览器中预览页面效果。 在 Visual Studio 中运行 HTML 文件并不复杂,只要配置正确,可以快速预览网页效果。以下是详细步骤,…

    2025年12月23日
    000
  • html5如何使用视频_在HTML5中嵌入与控制视频播放【播放】

    可使用HTML5的元素嵌入视频并实现播放控制:通过src、controls等属性基础嵌入;用JavaScript调用play()、pause()等方法控制行为;配合autoplay与muted实现自动播放;采用响应式容器适配多屏;监听error事件并用canPlayType()处理兼容性问题。 如果…

    2025年12月23日
    000
  • 使用Bulma创建固定导航栏、页脚与可滚动内容区域的教程

    本文详细介绍了如何在bulma框架中实现固定顶部导航栏、固定底部页脚,并使中间内容区域可独立滚动。通过利用bulma提供的`is-fixed-top`、`is-fixed-bottom`类以及在`html>`标签上添加相应的`has-navbar-fixed-top`和`has-navbar-…

    2025年12月23日
    000

发表回复

登录后才能评论
关注微信