Visual Studio .NET 2003的升级功能

编译/天行
关键词  Visual Studio  J#  移动设备 
本文介绍了Visual Studio .NET2003中对J#支持,对移劝开发的支持,改进的调试以及其它一些功能。

无论何时升级一个受欢迎的工具时,都会存在着兼容性、版本以及有关方法学的变化问题。Visual Studio .NET 2003的发布也不例外。但是各位开发人员可以放心,Visual Studio .NET 2003已经将变化保持到了最低限度,并且还可发现它已添加类似Visual J#那样的新功能。这里将讨论 .NET Framework 1.1以及Visual Studio .NET 2003的一些新特性,包括移动支持和改进调试。
如果你问开发人员对Visual Studio.NET 2003和Microsoft .NET Framework 1.1的感觉如何,可能会得到一个冰冷的答复。他们对调试器中缺乏类似break、Edit以及continue这样的功能感到非常失望。如果真是这样的话,别气馁。如果你认为在这个新版本中没有什么新的或重要的东西,那么请再看看。实际上有大量新的令人兴奋的功能,如果你还不那么确定是否需要深入地进行研究的话,可以逐步地去理解它。在安装了Visual Studio .NET 2003之后仍然可以运行Visual Studio .NET 2002。

代码兼容性变化
Framework中最大的“兼容性”变化(会使现存的代码在升级时产生问题)在于它的XML兼容性的变化。在System.Xml.Xsl.XslTransform中,Load和Transform方法需要使用XmlResolver变量了。唯一的其他变化是System.Environment.HasShutdownStarted属性现在是Static,而System.Security.Cryptography.DSACryptoServiceProvider类现在是密封的(或在Visual Basic .NET是不可继承的)。实际上,还有七个其他的变化会使代码产生兼容性问题,但它们在内部库iehost和iiehost中。剩余的变化根本不会影响代码。此外,还有对 .NET Framework的多版本支持。你可以使用启动条件创建针对于.NET Framework特定版本的安装程序(installers)。启动条件检测版本正确性,必要时重定向用户到相应的网络位置下载重发布内容。
新语言: Visual J# .NET 2003
也许1.1版.NET Framework最大的特色之一就是支持Visual J# .NET 2003,Visual J# .NET 2003是Java语言的一个托管版本。它不是Java平台,但Java开发人员使用它时会感到非常自在。 Visual J# .NET也支持Visual J++ 6.0大多数的特色,包括Microsoft扩展。加上可以将一些Java二进制代码进行转换后在CLR中运行,对于Java开发人来说,Visual J# .NET不愧是一个相当小巧精致的开发包。
由于Visual J# .NET仅仅是另一门针对CLR的语言,你也可以开发C#和Visual Basic .NET开发人员可以开发的应用程序(比如Web services、ASP.NET等等)。你也可以充分享受.NET Framework的安全性、跨语言性、部署特性。
Visual J# Binary Converter Tool将把Java二进制代码转换为微软中间语言(MSIL)。然而,应该注意到,它适应于大多数Java Development Kit (JDK) level 1.1.4的库和应用程序,但不是对所有的都合适。移植的首选方法是将Java语言源代码预编译为Visual J# .NET,这个工具只是最后的选择办法。
 Visual J# .NET用于提供类库支持,功能上大多等同于数Visual J++ 6.0中包含的JDK level 1.1.4开发包。同时它还提供了计算机科学课程College Board’s Advanced Placement中指定的各个类。Visual J# .NET也支持Windows Foundation Classes (WFC)库以及下列com.ms.包:com.ms.lang, com.ms.dll, com.ms.com, com.ms.win32, com.ms.util, 和com.ms.jdbc.odbc。
Visual J# .NET编译器不能将Java语言的源代码编译成Java语言二进制代码,但反而可以编译成MSIL。Visual J# .NET不支持applets开发,不能在浏览器中接纳applets,也不能创建运行在Java VW上的应用程序。然而,你可以创建Windows Forms控件,它们在同时安装有1.1版.NET Framework运行库和1.1版J#重发布包(Redistributable Package)的客户端机器浏览器中可以表现得非常出色。
 Visual J# .NET也不支持Java Native Interface (JNI),Raw Native Interface (RNI)和远程方法调用(RMI)。图1显示了Java二进制代码,源代码、JDK和.NET Framework之间的关系。


Java二进制代码可以转换为MSIL,尽管这不是推荐做法。再说一次,最好的做法是将Java语言源代码转换为Visual J# .NET,那样的话,最终结果就是纯粹的Visual J#.NET源代码。甚至最佳的方案是完全删除JDK支持,直接重新编码到.NET Framework。在那种情况下,你就可以转向针对CLR的代码,而不需在遗留的二进制代码或JDK库那儿进行一些无为的努力。你将注意到,Visual J# .NET完全可以同时支持JDK-level 1.1.4托管库和.NET Framework。
现在,让我们来看一看Visual J# .NET,并将它比作C#。代码1显示了一个简单的用C#在Visual Studio .NET 2003中开发的Hello World应用程序。代码2显示的是同一个项目,但是用的语言是Visual J# .NET。
代码1:

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;

namespace HelloCS
{
    ///


    /// Summary description for Form1.
    ///

    public class Form1 : System.Windows.Forms.Form
    {
        private System.Windows.Forms.Button button1;
        ///
        /// Required designer variable.
        ///

        private System.ComponentModel.Container components = null;

        public Form1()
        {
            //
            // Required for Windows Form Designer support
            //
            InitializeComponent();

            //
            // TODO: Add any constructor code after
            // InitializeComponent call
            //
        }

 ......

    }
}

代码2:

package HelloJS;

import System.Drawing.*;
import System.Collections.*;
import System.ComponentModel.*;

/**
 * Summary description for Form1.
 */
public class Form1 extends System.Windows.Forms.Form
{
    private System.Windows.Forms.Button button1;
    /**
     * Required designer variable.
     */
    private System.ComponentModel.Container components = null;

    public Form1()
    {
        //
        // Required for Windows Form Designer support
        //
        InitializeComponent();

        //
        // TODO: Add any constructor code after InitializeComponent call
        //
    }


 ......

}

正如你所能看见的,这两个程序很相似。using语句成了Import语句。C#的bool数据类型在Visual J# .NET中是Boolean。在C#中派生一个类使用克隆的方法,如下所示:
public class Form1 : System.Windows.Forms.Form
Visual J# .NET则使用extends关键字:
public class Form1 extends System.Windows.Forms.Form
存在两个明显的差异。主要一点要记住的是,Visual J# .NET是Java语言,而不是Java开发平台。它可以使Java 开发人员(尤其是使用J++的开发人员)充分利用它们的技能并改善现有的代码质量。

移动设备支持
尽管此刻看起来不算重要,因为针对Pocket PC和由Windows CE驱动的设备的开发正在如火如荼的进行着,对移动设备的支持还是无限量的。很容易就可以想象为这些设备开发各种程序具有的重要意义。它们很方便,无论走到哪里,你都可以带上你的数据,你可以对之进行修改,或将它带回到桌面电脑。
如果你已经注意了用于开发移动设备二进制客户端的智能设备扩展(Smart Device Extensions)的beta版,或用于开发针对移动设备的Web应用程序的Microsoft Mobile Internet Toolkit的beta版,你可能已经发现那有少量名字上的变化。你再也不会使用Mobile Internet Toolkit了。现在,你创建一个移动Web应用程序,并将移动Web控件放置到移动Web Forms上。至于紧凑框架(Compact Framework),你仍然可以创建智能设备应用程序。
一般说来,开发移动应用程序在最终版本中比现在使用的beta版顺利多了。例如,就目前来说,仿真器在多数情况下运行似乎是良好的。让我来解释一下移动客户端和Web应用程序的情况。

移动客户端应用程序
顾名思义,.NET紧凑框架是1.1版的.NET Framework的一个子集。在.NET紧凑框架中,Windows CE中没有的技术支持它也没有,像Active Directory(r)或Enterprise Services;但也没有可能已经包含的某些功能的支持,比如.NET远程化(Remoting)以及配置。
然而,它包含所有的基本工具,包括sockets、数据存取、调用Web Services支持以及图形。我可以编写一个快速的实用程序从URL下载图像,并立刻将它显示在PictureBox中。你可以很轻松地从流中获取一个位图对象,也可以从HttpWebResponse对象返回一个流。结合这两点,你就可以动态地从URL加载图像了,代码3所示。

Imports System.Net
Imports System.IO

Private Sub LoadPictureFromURL(ByVal pb As PictureBox, _
  ByVal URL As String)
    Dim MyStream As Stream
    Try
        '-- Create request and response objects
        Dim Request As HttpWebRequest = _
          CType(WebRequest.Create(URL), HttpWebRequest)
        Dim Response As HttpWebResponse = _
          CType(Request.GetResponse(), HttpWebResponse)
        '-- Get the response back as a Stream
        MyStream = Response.GetResponseStream()
        '-- Create a bitmap from that Stream
        Dim Bm As Bitmap = New Bitmap(MyStream)
        '-- Set the bitmap into the Picturebox
        pb.Image = Bm
        '-- Close the stream
        MyStream.Close()
    Catch ex As Exception
        If Not MyStream Is Nothing Then
            MyStream.Close()
        End If
        MsgBox(ex.Message)
    End Try
End Sub

从Beta1版起,紧凑框架小组就添加了DataGrid控件,尽管找到DataGrid控件还是比较困难的。在某些情况下,DataGrid在Visual Studio .NET工具箱中不显示。选择工具箱,再选中添加/删除项,然后在添加/删除对话框中按下重设按钮,之后就可以显示该控件了。Windows CE中其他较酷的控件也可以得到,比如TreeView、Toolbar、InputPanel、ListView、ProgressBar、TabControl、StatusBar以及TrackBar等。
对于移动应用程序来说有一个特性我确实很喜欢,那就是,你可以在.NET Framework的桌面版本中你可以直接返回一个.NET紧凑框架编译版的程序集(移动应用程序),而不需要进行预编译。为此,微软在程序集清单(manifest)中提供了一个Retargetable枚举关键字。我不知道这是不是一个好的举措,但是它确实可以很方便就知道一个移动应用程序能不能在桌面上运行。这个特性是不可逆,也即你不能在一个设备上复制一个针对桌面.NET Framework的应用程序,然后没有预编译就运行。
你一定要注意不要将移动应用程序设计得过于复杂。应用程序的界面一定要简单。输入笔(stylus)和软件键盘限制性因素,移动应用程序的总目标是让用户用最简单的界面最快的输入数据。
你可以在PC上使用附带了Visual Studio .NET 2003的硬件和软件Pocket PC仿真器调试移动应用程序。注意写代码时甚至不需要使用硬件设备。准备部署时,你可以直接部署到设备或创建一个CAB文件,它可以用来在设备上安装应用程序。
我已经编写了一个小的叫做FnetSchedule 的移动应用程序,它访问站点http://www.franklins.net/fnservice/schedule.asmx中的Web Service,并返回一个DataSet。该数据集包含了一个Visual Basic .NET在即内行(hands-on)类的时间进度表,还附带了该位置的图片,如图2所示。你可以访问站点:http://www.franklins.net/dotnet 得到该信息。

移动Web应用程序
移动Web应用程序是ASP.NET应用程序,主要是针对于类似WAP可兼容手机的设备。更小的页面,少量生成的HTML和代码,缩小的用户界面只是一个开头。和它们的老大哥ASP.NET应用程序一样,移动Web应用程序利用了服务器端控件来提交设备特定的内容。
有关移动Web应用程序的最佳消息是,你可以编写一个应用程序,访问任何的设备,包括手机。System.Mobile.Web.UI.MobileControls中的控件支持的设备各种各样,多达200多种,并且这个数字一直在上升。所有的设备功能都存储在Web服务器的Machine.Config文件中。你可以在站点http://asp.net/mobile/deviceupdate.aspx下载设备升级。
移动Web Form控件有多种多样,包括:AdRotator、Calendar、Command (按钮)、CompareValidator、CustomValidator、DeviceSpecific、Image、Label、Link、List、ObjectList、Panel、PhoneCall、RangeValidator、RegularExpressionValidator、 RequiredFieldValidator、SelectionList、StyleSheet、TextBox、TextView以及ValidationSummary。
和标准ASP.NET应用程序一样,基于浏览器的HTML控件也可以通过类似JavaScript和VBScript客户端脚本语言进行访问。
在各个控件当中,这里我需要指出的是SelectionList控件,该控件可以是列表、下拉列表或组合框。可以选择多个项目,选择时不会导致窗体递回。而且,SelectionList也不支持分页,所以对于小的列表比较理想。
DeviceSpecific控件提供自有设备相关内容的简单方法。你也可以根据客户端设备的类型提交不同的代码和HTML。
TextView控件显示带有可选标记标签的任意数量的文本。TextView控件中文本的格式与窗体中文字正文中的那样没有两样。然而,不像窗体中文字正文,你可以设置TextView控件中的文本。TextView控件支持内部分页。
PhoneCall控件是一个简单易用的控件,它是基于文本的,只用于输出,可以用来表示电话号码。对于类似可以用来打电话的手机那样的设备,PhoneCall控件就表示交互式元素,激活时就可以打电话。另一方面,电话号码显示为带可选超级链接的文本。
最后,ObjectList控件提供了一个功能丰富的数据对象列表视图。ObjectList控件通过使用设备模板集和列表控件的内部分页继承了它的大部分行为,包括支持模板表示,但是功能更加强大。
我可以将我的FnetSchedule应用程序作为移动Web应用程序,而且只需作少量的修改。你可以在站点http://www.franklins.net/mobile/schedule中使用的你的移动设备访问它。

C++检查
在Visual Studio .NET 2003新版本的C++也许是最重要的升级。现在C++程序员可以和C#访问同一个Windows Forms引擎。这个特性包括对工具箱和服务器浏览器的完全支持,这就允许你在Windows Forms应用程序中直接对控件和组件进行拖放或剪切粘贴操作。此外,你可以简单地通过属性表格操作控件和组建的属性。
Visual C++ .NET也比前一版本更符合ANSI。该版本有大量的中断变化,许多变化都采取编译器出错的形式,但是他们在前一版本中都忽略了。然而,也有大量的无声的或运行时错误。由于这个一致性,在许多情况下都可以编译为其他平台开发的C++代码。
编译器方面的变化包括:
u 一个功能选项。允许你创建一个值类型方法的代表
u /arch (最小CPU体系结构)编译器选项。添加该选项可以利用流动SIMD扩展(SSE)和SSE2指令
u /G7 (处理器最优化)编译器选项。告诉编译器为特定的处理器生成优化代码
u 增强/GS 编译器选项。有助于防止局部变量直接缓冲溢出(direct buffer overruns)
u /Zm编译器选项。指定预编译头文件内存分配限制
u /noBool选项已被删除
u /Gf不重要,将在Visual C++的下一个版本中删除。
内部_InterlockedCompareExchange、_InterlockedDecrement、_InterlockedExchange、_InterlockedExchangeAdd和_InterlockedIncrement已经文档化了,内部_ReadWriteBarrier也已添加。这就有效地阻塞了全局内存地读写优化,在确保多线程应用程序代码全局变量状态在特定点上是很有用的。
也添加了少数链接选项:/ASSEMBLYDEBUG发出Debuggable属性,跟踪调试信息,禁用JIT优化;/ASSEMBLYLINKRESOURCE创建到输出文件中.NET Framework资源的链接;/DELAYSIGN允许你只能将公共密钥(public key放在程序集中;/KEYFILE指定了强名称钥匙文件;/KEYCONTAINER指定了钥匙容器;/SAFESEH告诉连接器,如果也可以生成图像安全异常处理器表,只生成一个图像。
Visual C++ .NET提供了新属性页、大量新的对象,以及现有对象的新属性和方法。现有对象增强了项目构建模型。属性页包括托管资源属性页、XML数据生成器工具、托管包装器、初始interop页以及辅助托管包装器属性页。

Oracle和ODBC新数据提供者
也许第二个最大的新特性(取决于Oracle和ODBC开发对你的重要程度)是添加了这两个新的ADO.NET数据提供者,我不想评价他们是如何的好;我只想说,迄今为止,对使用ODBC访问DB2的任何报道都是褒扬的。现在你可以避免COM层(OLE DB)而直接编码到ODBC API (ODBC.DLL)和/或托管代码Oracle提供商,并且只需要使用你已经熟悉和喜爱的ADO.NET对象。
另一个变化是System.Data.SqlClient.SqlDataReader的HasRows属性值决定读取器是否返回数据。这使得处理空的结果集时更简单。
IPv6
Internet就要用完现行的255.255.255.255格式的IP地址了。静态IP地址的需求量在持续的上涨。类似网络地址传输(NAT)的复杂软硬件方案以及Web站点的IP共享在解决只有2554或大约4, 300, 000, 000个唯一用作IP地址的号码这个问题时是必不可少的。这就成了一个问题了。
在1995年,因特网工程任务组(Internet Engineering Task Force ,IETF)发布了Internet Protocol version 6 (IPv6)的基本规范。现在,多数Internet仍使用有近20年历史的IPv4。IPv6预计将逐渐地替换掉IPv4,而在过渡期间,这两种协议还要共存好几年的时间。
IPv6地址是128位,而IPv4只有32位。根据WIDE项目,如果IPv4地址总数量表示为毫米,IPv6地址总空间将是银河系直径的80倍。这样地址就够用了,你不那样认为吗?
除了添加了更多的IP地址之外,IPv6也在路由和无状态网络自动配置(routing and stateless network autoconfiguration)等方面对IPv4作了一些改进。路由器可以动态管理和分配IP地址,并且不需要求助于动态主机配置协议(Dynamic Host Configuration Protocol,DHCP)。你可以在IPv6 Stateless Address Autoconfiguration(网址:http://www.normos.org/ietf/rfc/rfc2462.txt)读到所有的有关自动配置方面的信息。
IPv6另一个了不起的特性就是实现了真正的组播。这就使得路由器可以将同一个数据包发送到多个路由器,客户端也可以接进具有唯一目标IP地址的数据包流,因此不必每个客户端都去获取他们自己的数据流。
使用IPv4的现场网站广播(Webcast)乍看起来就像一个常规的网站广播。但实际上是将同一个数据报发送给多个客户端。它有点类似无线电广播技术,但只使用单波段。客户端可以架起天线来捕捉该数据。这就减少了基础结构的许多负担,而且每个人几乎在同时接收到相同的数据。
.NET Framework1.1在System.Net命名空间中包括IPv6支持。在不久的将来,你因该能够听到更多关于IPv6方面的信息。

Visual Studio .NET中的变化
我将马上回到.NET Framework 1.1这个话题,但先让我介绍一下Visual Studio .NET 2003中的有哪些新东西。
设计 Visual Studio .NET 2003的设计基本上是一样的,但是有点华丽。我发现在绕开开始页时更加轻松。不幸的是,你仍可能在这个迷宫中迷失方向,这种状况短期内是不会改变的。只需记住,在窗口标题栏处双击鼠标将它锁住,然后双击重新开锁,这样就可以逃过最糟糕的状况。同时记住,你也可以在Environment|General tab in the Tools | Options对话框点击Reset Window Layout按钮解决这个问题。
Visual Basic .NET中的自动完成功能  现在,当你键入Try时,Visual Basic .NET会自动添加Catch语句和End Try。这是一个非常令人满意的功能(应该一直保留下去),但是界面的自动实现又如何呢?
在Visual Basic .NET中,当你键入 Implements语句时,界面立刻就生成了。试试看,用下面的语句创建一个新的类:

Public Class Foo
    Implements IDisposable

End Class

只要你在IDisposable后面敲一下回车键,立刻出现下面的样子:
Public Class Foo
    Implements IDisposable

    Public Sub Dispose() Implements System.IDisposable.Dispose

    End Sub
End Class

添加Web引用在图3中,Add Web Reference对话框中的“Start Browsing for Web Services”窗格提供了本地和Internet上可用Web Service的Web链接。有趣的是,浏览本地机获取Web引用在Beta1下就可用了。但在最后还是删除了。我很高兴有能使用这个功能了。
添加Web引用之前,你也可以对它重新命名,如图4所示。


新的调试器功能  现在,我们可以通过管道进行远程调试,管道具有安全的好处,在TCP/IP中可找不到这种好处。使用管道进行调试需要Remote Debug Manager,该管理器仅对C++可用。调试器也支持SOS,它是一个很了不起的托管代码转储池,可从Command窗口中进行挂接。出错消息大体上已经改进了,尤其是在调试ASP.NET应用程序时。调试符号现在也可以驻留在一个单独的符号服务器中,可以是你自己的服务器,也可以是微软的公共符号服务器。如果出现异常,它就可以自动地下载下来。除此之外,还可进行一些新的调试安全性设置,例如,这样你就可以指定谁有调试的权限以及谁没有这个权限。

从Visual Studio .NET 2002移植设置
你可以将Visual Studio .NET前一版本某些选项对话框中各种设置复制到新的版本中。如果你在同一个机器上安装了不同版本的程序,首先,你启动Visual Studio .NET 2003,这时出现一个对话框,你可以在那里选择是否一直现有设置。这时应点击确认按钮,选择移植你的选择和设置。
方案资源管理器中的变化 Visual Studio众多目标中的一个目标就是使用底层源代码同步化设计器。这个想法现在进一步深化了。有一个新选项,它告诉Visual Studio .NET无论何时你调出一个特定的设计器,该设计器都将自动地在方案资源管理器选定。打开Projects and Solutions | Environment | Options对话框, 选中Track Active复选项即可。
企业服务  现在可以使用企业服务(Enterprise Services)中低级的注册服务了。也就是说,你可以直接使用企业服务而不需要从ServicedComponent中继承。
ASP.NET特性 在这里最大的变化就是System.Web.UI.Page.ViewStateUserKey属性。你以前可能有此经历,ASP.NET管理ViewState时可能会是不确定的。在“ASP.NET中的Viewstate优化策略”中有一篇很好的文章概括了这方面的一些缺陷。
不仅要注意可伸缩性问题,还要注意安全性的问题。__VIEWSTATE变量是可以被黑(hack)的,一次点击攻击(one-click attacks)就可以用它打开你的ASP.NET应用程序。
设置ViewStateUserKey属性可以帮助使你的应用程序户避免遭受一次点击攻击。它是通过允许你为用于单个用户的__VIEWSTATE变量分配标识符的方式完成此功能的。
你可以将该属性设置为任何值,比如用户会话ID,但应该意识到,你必须在页面处理的Page_Init阶段设置该属性。在Page_Load阶段设置该属性将导致异常抛出。
对ASP.NET作一些新的变化之后,Checkbox、ListBox、ListControl、RadioButtonList以及Dropdown Listbox控件现在可以支持SelectedValue属性。
Enterprise Instrumentation Framework  Enterprise Instrumentation Framework (EIF)带有事件日志、跟踪以及性能计数器。EIF可以减少业务开发维护成本,帮助客户在高产量(high-volume)生产环境中进行有效的监视并排除故障。为了统一内建在Windows中的现有事件日志和跟踪机制,EIF提供了一个一致的、低配置(low-profile)的API和配置层。开发人员可以使用这个特性公布技术支持小组审计、出错、警告、业务事件以及诊断事件以便进行监视和分析。简言之,你在更大范围的环境中获得了更好的仪器设备。
支持世界时  世界时是国际标准时间,所有其他的时间都按照它来计算。调整世界时间(Coordinated Universal Time,UTC)以前称为格林威治标准时间(GMT)。.NET Framework中有几个类已进行升级以支持用UTC表示的时间值。
在Windows Management Instrumentation (WMI)中的日期和时间是以DMTF datetime格式表示的。这个格式在WMI SDK文档中已有解释(SDK可以从Windows Management Instrumentation (WMI) Tools中获取)。在DMPT中最低精度是毫秒,而在DateTime中它是一滴答(Tick),一滴答等于100纳秒。从滴答转换时,时间值要圆整为最靠近的毫秒值。
还有一个新的System.Management.ManagementDateTimeConverter类,可以用它来在DMTF datetime 格式和CLR-compliant DateTime 格式之间进行转换。
SMP线程同步.NET Framework 1.1增加了多处理器线程同步的功能(易失读写或内存刷新)。当然,处理这些线程同步时应该小心慎重些。

小结
本文就介绍到这里。除了Windows Forms之外,本文概括的介绍了.NET Framework 1.1和Visual Studio .NET 2003中的所有主要变化。很难想像,在.NET中安装新的应用程序不会破坏或替换老的程序。当然,了解我所熟悉的   .NET Framework方面的内容,应该没有什么大惊小怪的了,因为删除版本问题仍是一个主要的问题。但是,过去我常常花费数小时的业余时间去恢复一个骗子(rogue)安装程序在我系统中的“胡作非为”;我不知道,使用了这些“新发现”后,我的业余时间还会怎么度过。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值