浅尝EffectiveCSharp_2

Item 3: 使用isas操作符,避免强制转型 Prefer the is or as Operators to Casts

  • The correct choice is to use the as operator whenever you can because it
    is safer than blindly casting and is more efficient at runtime. The as and
    is operators do not perform any user-defined conversions. They succeed
    only if the runtime type matches the sought type; they never construct a
    new object to satisfy a request.
    应该是尽可能地使用as操作符,因为它比强制转型要安全,而且在运行时更有效率。as和is操作符都不执行任何用户自定义的转换。只有当运行时类型与目标转换类型匹配时,它们才会转换成功。它们永远不会在转换过程中构造新的对象。The correct choice is to use the as operator whenever you can because it is safer than blindly casting and is more efficient at runtime. The as and is operators do not perform any user-defined conversions. They succeed only if the runtime type matches the sought type; they never construct a new object to satisfy a request.
  • 看一个例子,以下是一个将任意Object类型转换成MyType类型。Take a look at an example. You write a piece of code that needs to convert an arbitrary object into an instance of MyType. You could write it this way
    1 object o = Factory.GetObject();
    2  // Version one:
    3  MyType t = o as MyType;
    4  if (t != null)
    5 {
    6  // work with t, it's a MyType.
    7  }
    8  else
    9 {
    10  // report the failure.
    11  }
    或者你可以这样写:
    1 object o = Factory.GetObject();
    2 // Version two:
    3 try
    4 {
    5 MyType t;
    6 t = (MyType)o;
    7 // work with T, it's a MyType.
    8 }
    9 catch (InvalidCastException)
    10 {
    11 // report the conversion failure.
    12 }
  • 转型之后要判断是否是null而且要捕获异常,而用as只要看返回的值是否是null。with casts, you need to check null and catch exceptions. Using as, you simply check the returned reference against null.
  • foreach循环用的是强制转型,因为foreach需要强制转型来支持值类型和引用类型。foreach uses a cast operation to perform conversions from an object to the type used in the loop.foreach needs to use casts to support both value types and reference types.

Item 4:使用Conditional特性,避免#if条件编译 Use Conditional Attributes Instead of #if

  • 这个方法比条件编译#if/#endif更加清晰明白。编译器可以识别Conditional属性,当条件属性被应用时,编译器可以很好的完成工作。条件属性是在方法上使用的,所以这就使用你必须把不同条件下使用的代码要写到不同的方法里去。  It’s a cleaner way to describe conditional compilation than #if/#endif. The compiler understands the Conditional attribute, so it can do a better job of verifying code when conditional attributes are applied. The conditional attribute is applied at the method level, so it forces you to separate conditional code into distinct methods. Use the Conditional attribute instead of #if/#endif blocks when you create conditional code blocks.
    1 private void CheckStateBad()
    2 {
    3 // The Old way:
    4 #if DEBUG
    5 Trace.WriteLine("Entering CheckState for Person");
    6 string methodName = new StackTrace().GetFrame(1).GetMethod().Name;
    7 Debug.Assert(lastName != null, methodName, "Last Name cannot be null");
    8 Debug.Assert(lastName.Length > 0, methodName, "Last Name cannot be blank");
    9 Debug.Assert(firstName != null, methodName, "First Name cannot be null");
    10 Debug.Assert(firstName.Length > 0, methodName, "First Name cannot be blank");
    11 Trace.WriteLine("Exiting CheckState for Person");
    12 #endif
    13 }
  • 上面的代码中使用#if块,会在debug和release版本中建立一个空方法。Using the #if and #endif pragmas, you’ve created an empty method in your release builds. The CheckState() method gets called in all builds, release and debug. It doesn’t do anything in the release builds, but you pay for the method call. You also pay a small cost to load and JIT the empty routine.
  • C#有个更好的选择,那就是条件属性。使用条件属性,你可以使你类中的部分方法孤立出来。C# has a better alternative: the Conditional attribute. Using the Conditional attribute, you can isolate functions that should be part of your classes only when a particular environment variable is defined or set to a certain value.
    public string LastName
    {
    get
    {
    CheckState();
    return lastName;
    }
    set
    {
    CheckState();
    lastName
    = value;
    CheckState();
    }
    }
    [Conditional(
    "DEBUG")]
    private void CheckState()
    {
    // same code as above
    }

    Debug状态下
    1 public string LastName
    2 {
    3 get
    4 {
    5 CheckState();
    6 return lastName;
    7 }
    8 set
    9 {
    10 CheckState();
    11 lastName = value;
    12 CheckState();
    13 }
    14 }
    运行状态下
    1 public string LastName
    2 {
    3 get
    4 {
    5 return lastName;
    6 }
    7 set
    8 {
    9 lastName = value;
    10 CheckState();
    11 }
    12 }
  • 不管DEBUG环境变量是否被定义,CheckState()方法总会被编译且存在于程序集中。这或许看上去是低效的,但这只是占用一点硬盘空间,CheckState()函数不会被载入到内存,更不会被JITed。 Whether the DEBUG environment variable is defined or not, the CheckState() method is compiled and delivered with the assembly. That might seem inefficient, but the only cost is disk space. The CheckState() function does not get loaded into memory and JITed unless it is called.
  • 你也可以创建一个依赖于更多环境变量的变量。多条件时是以OR的形式并列的。下面这个版本的CheckState会在DEBUG或者TRACE为真时被调用。You can also create methods that depend on more than one environment variable. When you apply multiple conditional attributes, they are combined with OR. For example, this version of CheckState would be called when either DEBUG or TRACE is true
    [Conditional("DEBUG"),
    Conditional(
    "TRACE")]
    private void CheckState()
  • 条件属性只能在整个方法中应用,而且返回值只能是void。The Conditional attribute can be applied only to entire methods

原文地址:https://www.cnblogs.com/TivonStone/p/1719681.html