揭开.NET 2.0配置之谜(一)

2010-03-20 15:33 by 吴秦, 4828 阅读, 20 评论, 收藏, 编辑

此文是译文,原文是Jon Rista,Unraveling the Mysteries of .NET 2.0 Configuration,由于这篇文章比较长,所以我就分为几部分来翻译。

以前没有翻译过外文,看英文文章倒是也看得懂,现在才发现要翻译出来,而且质量要过关还是挺难的(对我来说)。若翻译有不当之处,请不吝赐教,以免此译文误导他人,在此谢过。不废话了,let's start!

致谢:560889223,他帮忙解释了population的翻译问题!

引言

.NET的美妙特点之一是它的XML配置功能。在.NET 1.x时代,常见的应用程设置、数据库连接字符串、ASP.NET Web服务器配置和基本的自定义配置数据可以存储在.config文件中。自定义配置节可以使用一些基本自定义结构,允许少数几种信息存储在.config文件中。然而更复杂的配置,最常见的实现是自定义XML结构和自定义解析代码。尽管有多种不同性能的方法完成同样的事情,这种代码将变得相当复杂。

随着.NET 2.0,自己编写(可能很复杂、低性能、繁琐)代码来管理自定义XML配置结构的时代已经结束了。.NET 2.0内置的XML配置子系统自定义配置能力已经大大革新,拥有一些非常有用的和节省时间的功能。几乎任何XML配置结构你可能需要相对更少的工作且更容易。此外,反序列化.config中的XML总是可以重载的。这使得任何XML结构可以不失去.NET 2.0配置支持的其它高级功能。

该系列

这是该系列的第一篇文章。开始使用.NET 2.0所要求的所有核心概念和知识点都在这第一篇文章中提供。但是,.NET 2.0可用的配置框架是广泛的。从本文可以看到,它有许多功能和一些隐藏功能,可以填补框架的空白和疏漏。要继续学习有关.NET 2.0的配置框架,其它文章可以在以下链接找到:

  1. 揭开.NET 2.0配置之谜
  2. 解码.NET 2.0配置之谜
  3. 破解.NET 2.0配置之谜

写此系列的缘由(The mystery)

在略微超过一年的时间里我一直在使用.NET 2.0,可悲的是,我花了许多不眠之夜去修修补补自定义配置模型。自定义XML配置处理不断持续的性能下降,每个应用程序需要一个新的模型,这依赖于配置是如何存储的以及如何需要访问(从哪里)。直到8个月前左右,我用Reflector凿开.NET 2.0框架的一些程序集,我遇到一个奇妙的小类:System.Configuration.ConfigurationSection。挖掘更深一点,我发现为数众多的框架类都继承自ConfigurationSection和一些其它的类。自那时起,我花了几个不眠之夜吸收尽可能多的.NET 2.0的新配置特性。

我只想说,在互联网上关于自定义配置节的真正能力的资料非常少。通过Internet搜索、数小时的用Reflector研究框架代码、持续的实验和用自定义配置节,我终于知道了我需要知道的。这是生命的救星。最终,能轻松容易地创建和管理自定义XML配置、简单易用、易于管理并且性能优越……我将在与大家分享这个圣杯。我要求的唯一回报就是让任何人和你认识的用.config文件的人——他们应该更好地写.NET代码,看到这篇文章从而节省通过数个月的挖掘代码、互联网论坛和博客来学习它。

有关配置的主题

本文的目标是覆盖所有的.NET 2.0的配置,以及揭露一些更严密保护的秘密(标注:无正式文档的,无事实证明的…种种原因),可以节省你大量的时间和麻烦。首先,我们总览核心命名空间,它揭露了所有的自定义配置疯狂之处。然后,我们将进入具体执行和使用自定义配置。讨论的议题如下:

  1. 命名空间:System.Configuration
  2. 对象模型配置概念
  3. 编写一个基本的配置节
  4. 使用自定义配置节
  5. 添加自定义元素
  6. 添加元素集合
  7. 高级元素集合
  8. 自定义配置节组
  9. 保存配置更改
  10. 配置技巧和窍门
  11. 高级配置主题
  12. 附录
    1.附录A:配置结构的级联
    2.附录B:包含外部配置文件

1、命名空间:System.Configuration

新的.NET 2.0的配置精华核心是System.Configuration命名空间。默认情况下,当引用了System.dll程序集,此命名空间是可用的。它包括.NET 1.1的所有功能,包括旧的ConfigurationSettings类(现在.NET 2.0不推荐使用了)。然而,为了获得.NET 2.0的新特性,你必须添加对System.Configuration.dll程序集的引用。在这个程序集里你会发现新的配置系统的核心,ConfigurationManager静态类。

ConfigurationManager类是一个全局的访问一个应用程序的配置的入口。由于类是静态的,其所有的成员也是静态的。这使得读取如AppSettingsConnectionStrings和自定义配置节轻而易举。虽然这类似于ConfigurationSettings类它也提供一些能够更加安全地访问应用程序的配置的新功能。这些新功能,也可以允许将配置设置保存到任何配置节:自定义或其他的。

除了ConfigurationManager类是自定义配置节的生命线。下面列出的基类可以帮助你编写自己的配置对象模型。还将有更多关于这方面的。除了一个基类集是一个校验集,可以用来确保你的自定义配置节的准确性。此外,如果你的需要很简单,只需要用一些预制的配置。

基本类型

  • ConfigurationSection - 配置节基类
  • ConfigurationSectionCollection - 配置节集合的基类
  • ConfigurationSectionGroup - 配置节组的基类
  • ConfigurationSectionGroupCollection - 配置节组集合的基类
  • ConfigurationElement - 配置元素的基类
  • ConfigurationElementCollection - 配置元素集合的基类
  • ConfigurationConverterBase - 自定义转换器基类*1
  • ConfigurationValidatorBase - 自定义验证器基类*2

支持类型

  • ConfigurationManager - 提供对客户端应用程序配置文件的访问
  • Configuration - 表示一个应用程序的配置
  • ConfigurationProperty - 表示属性或配置元素的子元素
  • ConfigurationPropertyAttribute - 以声明方式指示.NET Framework,以实例化配置属性
  • ConfigurationPropertyCollection - 配置属性的集合
  • ConfigurationPropertyOptions - 指定要应用于属性的选项

验证类型

  • CallbackValidator - 提供对对象的动态验证
  • CallbackValidatorAttribute - 指定用于代码验证的CallbackValidator对象
  • IntegerValidator - 对Int32值进行验证
  • IntegerValidatorAttribute - 以声明的方式指示.NET Framework对配置属性执行整数验证
  • LongValidator - 对Int64值进行验证。
  • LongValidatorAttribute - 以声明的方式指示.NET Framework对配置属性执行长整型验证
  • PositiveTimeSpanValidator - 对TimeSpan对象进行验证。
  • PositiveTimeSpanValidatorAttribute - 以声明的方式指示.NET Framework对配置属性执行时间验证
  • RegexStringValidator - 根据正则表达式提供的规则提供字符串验证
  • RegexStringValidatorAttribute - 以声明方式指示.NET Framework使用正则表达式在配置属性中执行字符串验证
  • StringValidator - 对字符串进行验证
  • StringValidatorAttribute - 以声明的方式指示.NET Framework对配置属性执行字符串验证
  • SubclassTypeValidator - 验证一个对象是否是指定类型的派生类*3
  • SubclassTypeValidatorAttribute - 以声明方式指示.NET Framework对配置属性执行验证
  • TimeSpanValidator - 对TimeSpan对象进行验证
  • TimeSpanValidatorAttribute - 以声明的方式指示.NET Framework对配置属性执行时间验证

转换器类型

  • CommaDelimitedStringCollectionConverter - 将以逗号分隔的字符串值和CommaDelimitedStringCollection对象相互转换
  • GenericEnumConverter - 在字符串和枚举类型之间进行转换
  • InfiniteIntConverter - 在字符串和标准无限或整数值之间转换
  • InfiniteTimeSpanConverter - 在字符串和标准无限TimeSpan值之间转换
  • TimeSpanMinutesConverter - 转换以分钟表示的时间跨度
  • TimeSpanMinutesOrInfiniteConverter - 转换以分钟表示(或作为标准的无限时间跨度)的TimeSpan
  • TimeSpanSecondsConverter - 转换以秒表示的时间跨度
  • TimeSpanSecondsOrInfiniteConverter - 转换以秒表示的TimeSpan,或将其转换为标准的无限时间跨度
  • TypeNameConverter - 在类型和字符串值之间转换
  • WhiteSpaceTrimStringConverter - 将字符串转换为它的规范化格式

预制的配置节

  • AppSettingsSection - 为<appSettings> 配置节提供配置系统支持
  • ConnectionStringsSection - 提供对<connectionStrings>配置节的编程访问
  • ProtectedConfigurationSection - 提供对configProtectedData配置节的编程访问
  • IgnoreSection - 为不是由System.Configuration类型处理的配置节提供包装类型定义

预制配置集合*4

  • CommaDelimitedStringCollection - 与CommaDelimitedStringCollectionConverter结合使用(译注:表示以逗号分隔的字符串元素的集合)
  • KeyValueConfigurationCollection - 用于在配置节中配置键/值对(译注:包含KeyValueConfigurationElement对象的集合)
  • NameValueConfigurationCollection - 用于在配置节中配置名称/值对(译注:包含NameValueConfigurationElement对象的集合)

注意:

  • *1自定义转换器用于在XML文件中字符串表示与配置对象模型中强(译注:natively,或者翻译为“原生”?下同)类型之间转换
  • *2自定义验证器是用来验证在配置对象模型强类型数据的准确性
  • *3这关系到配置对象模型的概念,将在下一节讨论
  • *4这些常见的配置集合可用于自定义配置节

2、对象模型配置概念

在我们接下来创建一些自定义配置之前,有必要先来学习一些对象模型配置的概念。.NET 2.0配置系统最终提供了一组对象表示配置设置的结构和强类型访问配置数据。这与在XML文件中存储和检索配置的更多通用的方法相反,它们通常需要通过DOM或读取流读取值,通过DOM或者写流将改变写回文件。在我私人写的更高级的配置系统中,包括一些缓存机制来加速读取和写配置值。创建一个高度可定制的配置文件,同时保持良好的性能一直是一个难点。

.NET 2.0的配置对象模型不在需要那些庞大的处理XML配置数据的方法。作为一个简单的例子,将ConnectionStrings节对通用配置元素的配置管理整合进ConfigurationManager对象,通过一个唯一的名字非常容易查找和访问一个指定的数据库连接串。这是因为有一个.NET 集合类,它列出连接字符串配置的对象。每一个连接字符串对象都被一个名字键标记。.NET类对XML元素的映射如下所示:

ConnectionStringsSection<connectionStrings>
ConnectionStringSettingsCollection [implicitly created]
ConnectionStringSettings <add name="MyConnection" connectionString="blahblah">

访问MyConnetcion就如下面所示代码一样简单:

 
string myConnectionString = 
    ConfigurationManager.ConnectionStrings["MyConnection"].ConnectionString;

ConnectionStrings非常简单,所以让我们来看一个经常使用,但不那么明显的.NET 2.0配置系统:<system.web>配置组。你可能不知道它,但是但这一个复杂的配置节使用了一组类,用这组类我们可以创建自定义的配置节。让我们以class>emement关系的形式来看一下System.Web.Configuration对象模型:

Class:

Element:

SystemWebSectionGroup <system.web>
AuthenticationSection <authentication>
AuthorizationSection <authorization>
CustomErrorsSection <customErrors>
CustomErrorsCollection [implicitly created]
CustomError <error statusCode="404" redirect="...">
HttpModulesSection <httpModules>
HttpModuleActionCollection [implicitly created]
HttpModuleAction <add name="myModule" type="...">
HttpHandlersSection <httpHandlers>
HttpHandlerActionCollection [implicitly created]
HttpModuleActionCollection <add verb="*" type="..." path="...">

这只是System.Web ASP.NET配置节组提供的一套完整的配置节的一小部分。这些设置都可以通过一个精巧包装的对象模型访问,它归根于System.Web.Configuration.SystemWebSectionGroup类。在事件的要求下,使用这个对象模型甚至可以将更新和保存回web.config文件,假设该代码有改变和保存的权限。

.NET 2.0配置系统用这个对象模型为我们处理解析、验证、安全和population(译注:关于 Population:这个词原型是Populate,有填充的含义。例如老外有时候表述给下拉列表增加列表项时,就说“Populate the list”。我想在文章里应该是指反序列话时往配置文件中写入配置元素吧)。除了编写自定义配置节,这是相当简单的,它完全去除了对XML的考虑,当在应用程序中使用你的配置时。不仅如此,在应用程序的任何地方都可以直接访问这个精美的包装、强类型、安全对象模型,而无需担心向注册表那样给自定义XML配置文件查找或存储文件路径。为不一致、不灵活、低性能的自定义配置管理器烦恼的时代一去不复返了。

3、编写一个基本的配置节

如果在这之前的东西吓到了你,别担心。编写代码来提供自定义配置节到你的应用程序非常简单。处理难看的XML、安全检查、类型转换等等绝大部分问题,已经被.NET 2.0框架中已有代码处理了。由于System.Configuration的一组基类集,要创建一个简单的配置节的实际代码量非常非常少。让我们开始创建一个含有一个字符串值、一个布尔值和一个时间跨度值的简单配置节。每一个配置节都必须继承ConfigurationSection基类,让我从以下内容开始:

代码#region Using Statements
using System;
using System.Configuration;
#endregionnamespace Examples.Configuration
{/// <summary>/// An example configuration section class./// </summary>public class ExampleSection: ConfigurationSection{#region Constructorsstatic ExampleSection(){// Predefine properties here}#endregion// Declare static property fields here// Declare expose properties here}
}

一旦你开始定义一个配置节类,你将必须定义有效的配置属性。一个配置属性,通过ConfigurationProperty类表示,描述了一个配置项,它将在你的配置节中可用。有两种方法定义配置属性,编程式(programmatic)和声明式(declarative)。这两种方法我个人都喜欢用,因为声明式方法有助于自描述的代码,编程式方法更严谨。这保证了只有你期望的确切的对象模型生成和支持,但是维护起来有些乏味,因为对一个配置属性两者都要更新。注:在这文章中,作为一个完整的例子我将使用这两种方法。

让我们开始往我们的示例配置节中填写代码。首先定义静态属性字段,然后在类的静态构造器中创建那些字段。最后通过编写C#属性暴露配置数据。自定义的配置节完整源码应该看起来像下面这样:

代码#region Using Statements
using System;
using System.Configuration;
#endregionnamespace Examples.Configuration
{/// <summary>/// An example configuration section class./// </summary>public class ExampleSection: ConfigurationSection{#region Constructors/// <summary>/// Predefines the valid properties and prepares/// the property collection./// </summary>static ExampleSection(){// Predefine properties heres_propString = new ConfigurationProperty("stringValue",typeof(string),null,ConfigurationPropertyOptions.IsRequired);s_propBool = new ConfigurationProperty("boolValue",typeof(bool),false,ConfigurationPropertyOptions.None);s_propTimeSpan = new ConfigurationProperty("timeSpanValue",typeof(TimeSpan),null,ConfigurationPropertyOptions.None);s_properties = new ConfigurationPropertyCollection();s_properties.Add(s_propString);s_properties.Add(s_propBool);s_properties.Add(s_propTimeSpan);}#endregion#region Static Fieldsprivate static ConfigurationProperty s_propString;private static ConfigurationProperty s_propBool;private static ConfigurationProperty s_propTimeSpan;private static ConfigurationPropertyCollection s_properties;#endregion#region Properties/// <summary>/// Gets the StringValue setting./// </summary>[ConfigurationProperty("stringValue", IsRequired=true)]public string StringValue{get { return (string)base[s_propString]; }}/// <summary>/// Gets the BooleanValue setting./// </summary>[ConfigurationProperty("boolValue")]public bool BooleanValue{get { return (bool)base[s_propBool]; }}/// <summary>/// Gets the TimeSpanValue setting./// </summary>[ConfigurationProperty("timeSpanValue")]public TimeSpan TimeSpanValue{get { return (TimeSpan)base[s_propTimeSpan]; }}/// <summary>/// Override the Properties collection and return our custom one./// </summary>protected override ConfigurationPropertyCollection Properties{get { return s_properties; }}#endregion}
}

一旦你完成了,就是这样。此自定义配置节准备就绪。如果你喜欢写更少的代码,你可以不用构造器和静态字段,将每个值用过一个字符串键存储在默认的属性集合中。这将导致配置节本身要求更少的代码,但是要求整理上更少的定义。上述属性将被下面的代码的替代,静态字段和构造器可以删掉。顺便说一下,这就是纯粹的声明式方法:

代码#region Properties/// <summary>/// Gets the StringValue setting./// </summary>[ConfigurationProperty("stringValue", IsRequired=true)]public string StringValue{get { return (string)base["stringValue"]; }}/// <summary>/// Gets the BooleanValue setting./// </summary>[ConfigurationProperty("boolValue")]public bool BooleanValue{get { return (bool)base["boolValue"]; }}/// <summary>/// Gets the TimeSpanValue setting./// </summary>[ConfigurationProperty("timeSpanValue")]public TimeSpan TimeSpanValue{get { return (TimeSpan)base["timeSpanValue"]; }}#endregion

一个快速笔记,ConfigurationProperty真正是什么。默认,除非一个自定义元素明确地写出,所有的ConfigurationProperty都定义在一个App.config或Web.config文件中。创建和自定义配置元素集合将在后面讨论。

4、使用自定义配置节

现在你已经为你的自定义配置写了一个类,则你需要在一个App.config文件中定义自定义节。你必须添加必要的XML,以便他能被.NET 2.0配置系统解析。App.config文件要改成下面的那样,ExampleSection才可用,假定上述代码已经被编译成Examples.Configuration.dll

代码<configuration><configSections><section name="example" type="Examples.Configuration.ExampleSection, Examples.Configuration" /></configSections><examplestringValue="A sample string value."boolValue="true"timeSpanValue="5:00:00"/>
</configuration>

<configSections>及其子节点的一个快速解释。与内置的配置节不一样,他们是隐式定义的,自定义配置节必须显式地定义。这是通过<configSections>元素和它相应的<section>子元素来完成的。应当指出,一个节的名字一般是很重要的,不能任意选择的。一会儿你就知道为什么了。一个配置节映射到一个完全限定的类名,其后是程序集名。选择性地,你可以指定区域性、版本、公钥(用于程序集的签名)值,如果你想确保只在特定的程序集的特定版本中搜索,当你的.config被解析时。在上面的例子中,字符串逗号之前的那部分是类名,后面那部分是程序集名(不包括.dll后缀)。

最后,你可以在代码中用ConfigurationManager类使用你的自定义配置了。ConfigurationManager提供了一个叫做GetSection的方法,它允许你访问任何已经定义了的自定义设置。当你访问自定义配置节是,通常最好用动态转换和检查是否为空,就像这样:

访问自定义配置节private string m_string;
private bool m_bool;
private TimeSpan m_timespan;void GetExampleSettings()
{ExampleSection section = ConfigurationManager.GetSection("example") as ExampleSection;if (section != null){m_string = section.StringValue;m_bool = section.BooleanValue;m_timespan = section.TimeSpanValue;}
}

这里最重要注意的是选择代表一个配置节根元素的名字。在App.config文件的例子中,节被定义为 “example”。因为调用GetSection()时加载节查找名字‘example’,在App.config中任何试图为“example“重命名为其他名字将导致GetExampleSettings()失败。这是不可以任意选择一个自定义配置节的名子,除非明确地设计调整以保持一致,可能是通过使用另一个配置节。




本文转自吴秦博客园博客,原文链接:http://www.cnblogs.com/skynet/archive/2010/03/20/1690475.html,如需转载请自行联系原作者

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/256194.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Pytorch基础(六)——激活函数

一、概念 激活函数顾名思义&#xff0c;就是一种可以给神经网络注入灵魂的一种方法&#xff0c;也可以称之为激活层。其计算就是将线性的函数转变为非线性函数的过程&#xff0c;只有这样&#xff0c;我们制作的深层神经网络才能无限逼近真实值。 自神经网络发展到目前为止&am…

android数据的五种存储方式

Android提供了5种方式存储数据1 使用SharedPreferences存储数据它的本质是基于XML文件存储key-value键值对数据&#xff0c;通常用来存储一些简单的配置信息。其存储位置在/data/data/< >/shared_prefs目录下。SharedPreferences对象本身只能获取数据而不支持存储和修改&…

【NOIP 模拟题】[T1] 等差数列(dp)

【题解】【dp】 【f[i][j]表示以i为结尾&#xff0c;j为公差的子序列个数】 【要注意有负数&#xff0c;所以将公差1000】 #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int const p9901; int f[1010][2010],n,a[1010]; lo…

走在网页游戏开发的路上(十)

页游资源管理 现在页游的规模越来越来大&#xff0c;游戏内容丰富&#xff0c;资源管理变得很重要。现在一款SNS页游的所有资源可达50M&#xff0c;MMO页游更高达几百M&#xff0c;不可能把资源放到一个文件里面、也不可能一次性加载完所有资源。按200kb/s的下载速度来算&#…

Pytorch基础(七)——线性层(全连接层)

一、概念 在神经网络中&#xff0c;我们通常用线性层来完成两层神经元间的线性变换。 按照官网的解释&#xff0c;Linear.weight也即A&#xff0c; 我们可以称之为权重矩阵&#xff0c;对其转置后乘以输入数据(一般都是一维张量)&#xff0c;加上Linear.bias即b偏置。 二、P…

跨线程取出控件的值的写法(不是跨线程赋予控件值)

//这个方法是跨线程取出控件的值&#xff0c;不是跨线程赋予控件值private delegate void DelegateGetControl(各种参数);private void GetControl(各种参数&#xff0c;和委托的参数是一样的){try{if (this.InvokeRequired){//如果是跨线程的控件&#xff0c;就调用委托去实现…

使系统生成50个0-9之间的随机数,将每个数字出现的次数 存入一个一维数组中,统计出现次数最多和出现次数最少的数字,及出现次数 和出现频率。...

int [] numsnew int[10]; for(int i0;i<50;i){ int num(int)(Math.random()*10);//随机生成0-9 nums[num];//生成随机数 对应下标位置 自增 } int maxIndex0;//存储出现最多次数的下标 int minIndex0;//存储出现最少次数的下标 //循环数组 for(int i1;i<nums.length;i){ …

PureMVC(AS3)剖析:吐槽

PureMVC&#xff08;AS3&#xff09;剖析&#xff1a;吐槽 写在前面 世上没有银弹——不存在适用于所有情况的框架&#xff0c;只有适合的框架。再者任何一个好的东西&#xff08;语言、框架等&#xff09;最终还取决于用的人&#xff0c;语言和框架本身并不能保证用户的代码清…

Pytorch基础(八)——正则化

一、概念 正则化在深度学习领域是为了防止训练结果过拟合而采取的一种方法。 1.1 过拟合 过拟合表示模型的泛化能力较差&#xff0c;体现在实际训练模型上就是在训练集表现很好&#xff0c;但是在测试集的效果一般。 过拟合的原因&#xff1a;1&#xff0c;模型过于复杂。2&…

uva 11997 K Smallest Sums 优先队列处理多路归并问题

题意&#xff1a;K个数组每组K个值&#xff0c;每次从一组中选一个&#xff0c;共K^k种&#xff0c;问前K个小的。 思路&#xff1a;优先队列处理多路归并&#xff0c;每个状态含有K个元素。详见刘汝佳算法指南。 1 #include<iostream>2 #include<cstdio>3 #includ…

.net生成随机字符串

生成随机字符串的工具类&#xff1a; /// <summary>/// 随机字符串工具类/// </summary>public class RandomTools{/// <summary>/// 随机系数/// </summary>public static int _RandIndex 0;#region 获取某个区间的一个随机数/// <summary>///…

【图像处理】——Python鼠标框选ROI(感兴趣)区域并且保存(含鼠标事件)

鼠标交互切割矩形 接下来,就是本文重点了。先吐个槽,网上有资源,但搜到的都是C++的。本来有点气馁的,还好,有官网在,文档写得很清楚,而且接口函数名字变化不大,稍微做下修改就行了。 import cv2global img global point1, point2 def on_mouse(event, x, y, flags, pa…

c++ 11 override final

C 11添加了两个继承控制关键字&#xff1a;override和final。 override确保在派生类中声明的重载函数跟基类的虚函数有相同的签名。final阻止类的进一步派生和虚函数的进一步重载 出处&#xff1a;http://www.cnblogs.com/zhangdongsheng/ 作者&#xff1a;张东升

泛型方法与桥方法

Java泛型中有存在一种方式叫做类型擦除&#xff0c;也就是说泛型在编译期间进行类型检验上做到有效安全&#xff0c;但是在运行当中&#xff0c;会将该泛型类型用顶层父类&#xff08;若无继承关系则用Object&#xff09;代替&#xff0c;然后再进行强转换成目标类型&#xff0…

Pytorch基础(九)——损失函数

一、概念 损失函数在深度学习领域是用来计算搭建模型预测的输出值和真实值之间的误差。 具体实现过程&#xff1a;在一个批次&#xff08;batch&#xff09;前向传播完成后&#xff0c;得到预测值&#xff0c;然后损失函数计算出预测值和真实值之间的差值&#xff0c;反向传播…

用程序猿思维、程序设计师思维两种方式写求斐波那契数列的方法。

//用Java实现斐波那契数列(Fibonacci) public class Test {public int f(int n)//n代表第几个数字。程序返回它相应的值{return n>2?f(n-1)f(n-2):1;//看似如此优雅的一句程序}//程序设计师的思维&#xff1a;会重构上面的代码。让他们更易读。推荐&#xff01;&#xff01…

【图像处理】——图像的差集、并集、补集、交集以及两个图像相减出现负数的处理方法

目录 目录 1、交集 2、差集 3、并集 4、补集 5、差为负值,和超过255的解决办法

Pytorch基础(十)——优化器(SGD,Adagrad,RMSprop,Adam,LBFGS等)

一、概念 Pytorch中优化器的目的&#xff1a;将损失函数计算出的差值Loss减小。 优化过程&#xff1a;优化器计算网络参数的梯度&#xff0c;然后使用一定的算法策略来对参数进行计算&#xff0c;用新的参数来重新进行训练&#xff0c;最终降低Loss。 其中官网提供了13种优化算…

【图像处理】——改变图像的大小(降采样重采样)下采样和上采样

转载自:https://jingyan.baidu.com/article/a3a3f81139be1f8da2eb8ade.html 上采样、下采样和金字塔加速参考:https://blog.csdn.net/Eastmount/article/details/89341077 目录 1、拉伸图片——重采样 2、缩小图片 1)三次插值法cv2.INTER_CUBIC