当前位置: 首页 > news >正文

做数据库与网站招什么人如何加强企业网站建设论文

做数据库与网站招什么人,如何加强企业网站建设论文,如何在国外做网站,装修设计费多少钱一平点击上方蓝字关注“汪宇杰博客”文#xff1a;Damir Arh译#xff1a;Edi Wang即使是具有良好 C# 技能的开发人员有时候也会编写可能会出现意外行为的代码。本文介绍了属于该类别的几个 C# 代码片段#xff0c;并解释了令人惊讶的行为背后的原因。Null 值我们都知道#xf… 点击上方蓝字关注“汪宇杰博客”文Damir Arh译Edi Wang即使是具有良好 C# 技能的开发人员有时候也会编写可能会出现意外行为的代码。本文介绍了属于该类别的几个 C# 代码片段并解释了令人惊讶的行为背后的原因。Null 值我们都知道如果处理不当空值null可能是危险的。使用一个空值对象例如在一个null对象上调用方法或访问它的一个属性会导致 NullReferenceException 例如object nullValue null;bool areNullValuesEqual nullValue.Equals(null);为了安全起见我们在使用引用类型之前需要确保它们不为 null 。如果不这样做可能会导致特定边缘情况下的未处理异常。虽然这样的错误偶尔会发生在每个人身上但我们几乎不能称之为意外行为。但是下面的代码呢string nullString (string)null;bool isStringType nullString is string;isStringType 的值是什么显式申明为字符串的变量是否也会在运行时作为字符串类型正确的答案是否null 值在运行时是没有类型的从某种程度上说这也会影响反射。当然您不能在空值上调用 GetType()因为会引发空引用异常object nullValue null;Type nullType nullValue.GetType();接下来我们看看可空的值类型int intValue 5;Nullableint nullableIntValue 5;bool areTypesEqual intValue.GetType() nullableIntValue.GetType();是否可以使用反射来区分可空值类型和不可空值类型答案是不可以上述代码中的两个变量返回相同的类型: System.Int32。不过这并不意味着反射对 NullableT 没有表示。Type intType typeof(int);Type nullableIntType typeof(Nullableint);bool areTypesEqual intType nullableIntType;此代码段中的类型是不同的。如预期的那样可空类型将用 System.Nullable1[[System.Int32] 表示。只有在检查值时才会将值视为反射中的不可空值。重载方法中的 null 值在转到其他话题之前让我们仔细了解在调用参数数量相同但类型不同的重载方法时如何处理空值。private string OverloadedMethod(object arg){    return object parameter;} private string OverloadedMethod(string arg){    return string parameter ;}如果我们使用空null值调用这个方法会发生什么情况var result OverloadedMethod(null);将调用哪个重载还是代码会因为方法调用不明确而无法编译在这种情况下代码可以编译并调用具有字符串参数的方法。通常当一个参数类型可以转换成一个参数类型 (即一个参数类型从另一个参数类型派生) 时代码可以编译。将调用具有更具体参数类型的方法。当这两种类型之间不可以转换时代码将不会编译。若要强制调用特定重载, 可以将空值强制转换为该参数类型var result parameteredMethod((object)null);算术运算我们大多数人并不经常使用位移位操作。让我们先刷新一下记忆。左移运算符 () 将二进制表示向左移动给定数量的位置var shifted 0b1 1; // 0b10同样, 右移位运算符 () 将二进制表示形式向右移动:var shifted 0b1 1; // 0b0当这些位bit到达终点时它们不会换行wrap。这就是为什么第二个表达式的结果是0。如果我们将位移动到足够远的左侧 (32位, 因为整数是32位数字)也会发生同样的情况var shifted 0b1;for (int i 0; i 32; i){    shifted shifted 1;}结果将再次为0。但是, 位移位运算符具有第二个操作数。我们可以向左移动 32位而不是向左移动1位32次并获得相同的结果。var shifted 0b1 32;是这样吗这是错的此表达式的结果将是1。为什么因为这就是运算符的定义方式。在应用操作之前第二个操作数将使用模数操作将被归一操作的位长度规范化即通过计算第二个操作数除以第一个操作数的位长度的剩余部分。我们刚才看到的示例中的第一个操作数是32位数字因此32 % 32 0。我们的数字将向左移动0位。这和把它移1位32次是不一样的。让我们继续操作 (和) | (或)。根据操作数的类型它们表示两种不同的操作对于布尔操作数它们充当逻辑运算符类似于 和 ||有一个区别它们是饥饿的eager即始终计算两个操作数即使在评估第一个操作数后就可以确定结果。对于整数类型它们充当逻辑按位运算符通常用于表示 Flag 的枚举类型。[Flags]private enum Colors{    None 0b0,    Red 0b1,    Green 0b10,    Blue 0b100}| 运算符用于组合标志Flag 运算符用于检查是否设置了标志Colors color Colors.Red | Colors.Green;bool isRed (color Colors.Red) Colors.Red;在上面的代码中我在按位逻辑操作前后加上括号以使代码更加清晰。此表达式中是否需要括号事实证明是的。与算术运算符不同按位逻辑运算符的优先级低于相等运算符。幸运的是由于类型检查没有括号的代码将无法编译。从 .NET Framework 4.0 起有一个更好的替代方法可用于检查标志您应该始终使用它而不是 运算符bool isRed color.HasFlag(Colors.Red);Math.Round()我们以Round为例继续聊算术运算操作。它如何在两个整数值 (例如 1.5) 之间的中点舍入值向上还是向下var rounded Math.Round(1.5);如果你预测是2你是对的。结果将是2。这是一般规则吗var rounded Math.Round(2.5);不。结果将再次为2。默认情况下中点值将Round到最接近的偶数值。您可以为方法提供第二个参数以显式请求此类行为var rounded Math.Round(2.5, MidpointRounding.ToEven);可以使用第二个参数的不同值更改行为var rounded Math.Round(2.5, MidpointRounding.AwayFromZero);有了这个明确的规则正值现在总是向上舍入。舍入数字也会受到浮点数精度的影响。var value 1.4f;var rounded Math.Round(value 0.1f);虽然中点值应舍入到最接近的偶数即 2但在这种情况下结果将是 1因为对于单精度浮点数0.1 没有精确的表示形式计算的数字实际上将小于 1.5 并因此Round到1。尽管在使用双精度浮点数时没有出现此特定问题但舍入错误仍可能发生尽管频率较低。因此在要求最大精度时应始终使用小数而不是浮动或双精度。类初始化最佳实践建议尽可能避免类构造函数中的类初始化以防止异常。所有这些对于静态构造函数来说都更加重要。您可能知道当我们尝试在运行时实例化静态构造函数时它在实例构造函数之前调用。这是实例化任何类时的初始化顺序静态字段 (仅限第一次类访问: 静态成员或第一个实例)静态构造函数 (仅限第一次类访问: 静态成员或第一个实例)实例字段 (每个实例)实例构造函数 (每个实例)让我们创建一个具有静态构造函数的类可以将其配置为引发异常public static class Config{    public static bool ThrowException { get; set; } true;}public class FailingClass{    static FailingClass()    {        if (Config.ThrowException)        {            throw new InvalidOperationException();        }    }}创建此类实例的任何尝试都会导致异常这不应该让人感到意外:var instance new FailingClass();但是它不会是 InvalidOperationException 。运行时将自动将其包装到 TypeInitializationException 中。如果要捕获异常并从中恢复这是需要注意的重要详细信息。try{    var failedInstance new FailingClass();}catch (TypeInitializationException) { }Config.ThrowException false;var instance new FailingClass();应用我们所学到的知识上面的代码应该捕获静态构造函数引发的异常更改配置以避免在以后的调用中引发异常最后成功地创建类的实例对吗不幸的是不对。类的静态构造函数只调用一次。如果它引发异常则每当您要创建实例或以任何其他方式访问类时都将重新引发此异常。在重新启动进程 (或应用程序域) 之前该类实际上无法使用。是的即使静态构造函数引发异常的可能性很小也是一个非常糟糕的想法。派生类中的初始化顺序对于派生类初始化顺序更加复杂。在边缘情况下这可能会给你带来麻烦。是时候做一个人为的例子了public class BaseClass{    public BaseClass()    {        VirtualMethod(1);    }    public virtual int VirtualMethod(int dividend)    {        return dividend / 1;    }}public class DerivedClass : BaseClass{    int divisor;    public DerivedClass()    {        divisor 1;    }    public override int VirtualMethod(int dividend)    {        return base.VirtualMethod(dividend / divisor);    }}你能在衍生类中发现一个问题吗当我尝试实例化它时, 会发生什么var instance new DerivedClass();将引发一个 DivideByZeroException 。为什么原因是派生类的初始化顺序首先实例字段按从派生最远的到基类的顺序进行初始化。其次构造函数按从基类到派生最远的类的顺序调用。由于在整个初始化过程中该类被视为 DerivedClass我们在 BaseClass 构造函数中调用 VirtualMethod 这个方法的实现其实是 DerivedClass 里的实现这时候DerivedClass 的构造函数还没机会初始化 divisor 字段。这意味着该值仍然为 0这导致了DivideByZeroException。在我们的示例中可以通过直接初始化除数字段而不是在构造函数中来解决此问题。然而该示例说明了为什么从构造函数调用虚拟方法可能很危险。当调用它们时它们在中定义的类的构造函数可能尚未调用因此它们可能会出现意外行为。多态性多态性是不同类以不同的方式实现相同接口的能力。不过我们通常期望单个实例始终使用相同的方法实现无论它是由哪个类型强制转换的。这样就可以将集合作为基类并在集合中的所有实例上调用特定方法从而为要调用的每个类型实现特定的方法。话虽如此但当我们在调用该方法之前向下转换实例时你能想出一种方法来调用不同的方法吗(即打破多态行为)var instance new DerivedClass();var result instance.Method(); // - Method in DerivedClassresult ((BaseClass)instance).Method(); // - Method in BaseClass正确的答案是: 通过使用 new 修饰符。public class BaseClass{    public virtual string Method()    {        return Method in BaseClass ;    }} public class DerivedClass : BaseClass{    public new string Method()    {        return Method in DerivedClass;    }}这将从其基类中隐藏 DerivedClass.Method因此在将实例转换为基类时调用 BaseClass.Method。这适用于基类基类可以有自己的方法实现。对于不能包含自己的方法实现的接口你能想出一个实现相同目标的方法吗var instance new DerivedClass();var result instance.Method(); // - Method in DerivedClassresult ((IInterface)instance).Method(); // - Method belonging to IInterface它是显式接口实现public interface IInterface{    string Method();}public class DerivedClass : IInterface{    public string Method()    {        return Method in DerivedClass;    }     string IInterface.Method()    {        return Method belonging to IInterface;    }}它通常用于向实现它的类的使用者隐藏接口方法除非他们将实例转换到该接口。但是如果我们希望在单个类中具有两个不同的方法实现它的效果也一样好。不过很难想出做这件事的好理由。迭代器迭代器是用于单步执行构造集合的结构通常使用 foreach 语句。它们由 IEnumerableT 类型表示。虽然它们很容易使用但由于一些编译器的魔力如果我们不能很好地理解内部工作原理我们很快就会陷入不正确用法的陷阱。让我们看一下这样的例子。我们将调用一个方法该方法从 using 内部返回一个 IEnumerableprivate IEnumerableint GetEnumerable(StringBuilder log){    using (var context new Context(log))    {        return Enumerable.Range(1, 5);    }}当然Context 类型实现了 IDisposable。它将向日志写入一条消息, 以指示何时输入和退出其作用域。在实际代码中, 此上下文可以被数据库连接所取代。在它里面, 将以流式的方式从返回的结果集中读取行。public class Context : IDisposable{    private readonly StringBuilder log;     public Context(StringBuilder log)    {        this.log log;        this.log.AppendLine(Context created);    }     public void Dispose()    {        this.log.AppendLine(Context disposed);    }}若要使用 GetEnumerable 返回值, 我们使用 foreach 循环var log new StringBuilder();foreach (var number in GetEnumerable(log)){    log.AppendLine(${number});}代码执行后日志的内容将是什么返回的值是否会在上下文创建和处置之间列出不他们不会Context createdContext disposed12345这意味着在我们的实际数据库示例中代码将失败--在从数据库中读取值之前连接将被关闭。我们如何修复代码以便只有在所有值都已迭代后才会释放上下文执行此操作的唯一方法是循环访问已在 GetEnumerable 方法中的集合private IEnumerableint GetEnumerable(StringBuilder log){    using (var context new Context(log))    {        foreach (var i in Enumerable.Range(1, 5))        {            yield return i;        }    }}当我们现在循环访问返回的 IEnumerable 时上下文将只按预期的方式在末尾进行释放Context created12345Context disposed如果您不熟悉 yield return 语句它是用于创建状态机的语法糖允许以增量方式执行使用它的方法中的代码因为生成的 IEnumerable 正在被迭代。这可以用下面的方法更好地解释private IEnumerableint GetCustomEnumerable(StringBuilder log){    log.AppendLine(before 1);    yield return 1;    log.AppendLine(before 2);    yield return 2;    log.AppendLine(before 3);    yield return 3;    log.AppendLine(before 4);    yield return 4;    log.AppendLine(before 5);    yield return 5;    log.AppendLine(before end);}若要查看这段代码的行为我们可以使用以下代码对其进行循环访问var log new StringBuilder();log.AppendLine(before enumeration);foreach (var number in GetCustomEnumerable(log)){    log.AppendLine(${number});}log.AppendLine(after enumeration);让我们看看代码执行后的日志内容before enumerationbefore 11before 22before 33before 44before 55before endafter enumeration我们可以看到, 对于我们遍历的每个值两个 yield return 语句之间的代码都会被执行。对于第一个值这是从方法开始到第一个 yield return 语句的代码。对于第二个值它是第一个和第二个 yield return 语句之间的代码。以此类推直到方法结束。当 foreach 循环在循环的最后一次迭代之后检查 IEnumerable 中的下一个值时将调用最后一个 yield return 语句之后的代码。同样值得注意的是每次我们通过 IEnumerable 迭代时都会执行此代码var log new StringBuilder();var enumerable GetCustomEnumerable(log);for (int i 1; i 2; i){    log.AppendLine($enumeration #{i});    foreach (var number in enumerable)    {        log.AppendLine(${number});    }}执行此代码后日志将具有以下内容enumeration #1before 11before 22before 33before 44before 55before endenumeration #2before 11before 22before 33before 44before 55before end为了防止每次我们通过 IEnumerable 迭代时执行代码最好将 IEnumerable 的结果存储到本地集合 (例如, list) 中如果我们计划多次使用它则从那里读取它var log new StringBuilder();var enumerable GetCustomEnumerable(log).ToList();for (int i 1; i 2; i){    log.AppendLine($enumeration #{i});    foreach (var number in enumerable)    {        log.AppendLine(${number});    }}现在代码将只执行一次--在我们创建列表时然后再对其进行迭代before 1before 2before 3before 4before 5before endenumeration #112345enumeration #212345当我们正在迭代的 IEnumerable 后面有缓慢的 I/O 操作时这一点尤其重要。数据库访问也是一个典型的例子。结论您是否正确地预测了文章中所有示例的行为如果没有您可能已经了解到当您不能完全确定特定功能是如何实现的时采取行为可能是危险的。不可能知道并记住一种语言中的每一个边缘案例因此当您对遇到的一段重要代码不确定时最好检查文档或自己先尝试一下。更重要的是这其中的任何一项都是为了避免编写可能会让其他开发人员感到惊讶的代码 (或者在经过一定时间后甚至可能是您)。尝试以不同的方式编写它或传递该可选参数的默认值 (如我们的 Math.Round 中的示例)以使意图更清晰。如果这行不通就写测试方法。他们将清楚地记录预期的行为你能正确地预测哪些在评论中让我们知道吧。Yacoub Masd 对该文章进行了技术审查。Suprotim Agarwal 对本文进行了编辑审查。
http://www.zqtcl.cn/news/55105/

相关文章:

  • 湛江网站建设制作维护太原网络营销招聘
  • 想搭网站做软件首先要学设么用dw个人网站怎么建立
  • 如何自己做框架开发网站代做关键词收录排名
  • 网站开发 实战沈阳创造价值网站
  • 做公众号封面图的网站重庆永川网站建设价格
  • 专注网站建设怎么样洋县住房和城乡建设管理局网站
  • 0基础学网站建设湖北建科建设工程有限公司网站
  • 做网站时如何上传图片jsp 做网站还是php
  • 宁波新亚建设公司网站专业网站设计发展前景
  • 简单网上书店网站建设php小语种网站怎么设计
  • 德州建设街小学网站2003系统网站建设
  • 电商网站 外包网站关键词优化怎么做
  • 中国二级建造师网官网东莞关键词排名seo
  • 清徐北京网站建设推广普通话的演讲稿
  • 怎样做公司的网站首页百度广告大全
  • 搭建个网站多少钱wordpress 打不开 怎么办
  • 交友征婚婚恋网站系统php+mysql.rar抖音矩阵排名软件seo
  • 怎么做服装外贸网站网站建设公司该怎么销售
  • 南充北京网站建设网站建设i
  • 展示页网站怎么做排名许昌seo推广
  • 网站上的动图都怎么做的网站建设会碰到什么问题
  • 佛山市专注网站建设平台襄阳网站建设需要多少钱
  • 重庆网站首页制作推广怎么做才可以赚钱
  • 淘宝客网站搭建教程甲马营seo网站优化的
  • 网站定制公司报价如何用visual做网站
  • 汉阳放心的建站企丿黄石网站制作
  • wordpress站做app门户网站是什么
  • 做技术开发的网站wordpress 防注册
  • 网站搜索功能怎么实现大连网站建设服务
  • 中国建设银行信用卡中心网站创新的常州做网站