相关疑难解决方法(0)

C#在foreach中重用变量是否有原因?

在C#中使用lambda表达式或匿名方法时,我们必须警惕对修改后的闭包陷阱的访问.例如:

foreach (var s in strings)
{
   query = query.Where(i => i.Prop == s); // access to modified closure
   ...
}
Run Code Online (Sandbox Code Playgroud)

由于修改后的闭包,上面的代码将导致Where查询中的所有子句都基于最终值s.

正如这里所解释的那样,这是因为上面循环中s声明的变量foreach在编译器中被翻译成这样:

string s;
while (enumerator.MoveNext())
{
   s = enumerator.Current;
   ...
}
Run Code Online (Sandbox Code Playgroud)

而不是像这样:

while (enumerator.MoveNext())
{
   string s;
   s = enumerator.Current;
   ...
}
Run Code Online (Sandbox Code Playgroud)

正如这里所指出的,循环外声明变量没有性能优势,在正常情况下,我能想到这样做的唯一原因是你计划在循环范围之外使用变量:

string s;
while (enumerator.MoveNext())
{
   s = enumerator.Current;
   ...
}
var finalString = s;
Run Code Online (Sandbox Code Playgroud)

但是,foreach循环中定义的变量不能在循环外使用: …

c# foreach lambda scope anonymous-methods

1631
推荐指数
4
解决办法
10万
查看次数

为什么typeA == typeB比typeA == typeof(TypeB)慢?

我最近一直在优化/基准测试一些代码,并遇到了这种方法:

public void SomeMethod(Type messageType)
{
    if (messageType == typeof(BroadcastMessage))
    {
        // ...
    }
    else if (messageType == typeof(DirectMessage))
    {
        // ...
    }
    else if (messageType == typeof(ClientListRequest))
    {
        // ...
    }
}
Run Code Online (Sandbox Code Playgroud)

这是从其他地方的性能关键循环typeof(...)调用的,因此我自然地假设所有这些调用都增加了不必要的开销(我知道微优化)并且可以移动到类中的私有字段.(我知道有更好的方法来重构这些代码,但是,我仍然想知道这里发生了什么.)

根据我的基准测试,情况并非如此(使用BenchmarkDotNet).

[DisassemblyDiagnoser(printAsm: true, printSource: true)]
[RyuJitX64Job]
public class Tests
{
    private Type a = typeof(string);
    private Type b = typeof(int);

    [Benchmark]
    public bool F1()
    {
        return a == typeof(int);
    }

    [Benchmark]
    public bool F2()
    {
        return a == b;
    }
}
Run Code Online (Sandbox Code Playgroud)

在我的机器上的结果(Window …

.net c# assembly x86-64

15
推荐指数
1
解决办法
513
查看次数

为什么接口 IOrderedEnumerable<T> 在 T 中不是协变的?

我正在查看 IOrderedEnumerable 的声明,令我惊讶的是它的 TElement 类型参数不是协变的。

public interface IOrderedEnumerable<TElement> : IEnumerable<TElement>, IEnumerable
{
    IOrderedEnumerable<TElement> CreateOrderedEnumerable<TKey>(Func<TElement, TKey> keySelector, IComparer<TKey> comparer, bool descending);
}
Run Code Online (Sandbox Code Playgroud)

它没有成为协变的原因是什么?

c# covariance

5
推荐指数
1
解决办法
198
查看次数

在C#中,事件处理程序参数是否反对?

如果我有一个引发事件的类,使用(例如)FrobbingEventArgs,我是否可以使用带有EventArgs的方法来处理它?

这是一些代码:

class Program
{
   static void Main(string[] args)
   {
      Frobber frobber = new Frobber();
      frobber.Frobbing += FrobberOnFrobbing;
      frobber.Frob();
   }

   private static void FrobberOnFrobbing(object sender,
       EventArgs e)
   {
      // Do something interesting. Note that the parameter is 'EventArgs'.
   }
}

internal class Frobber
{
   public event EventHandler<FrobbingEventArgs> Frobbing;
   public event EventHandler<FrobbedEventArgs> Frobbed;

   public void Frob()
   {
      OnFrobbing();

      // Frob.

      OnFrobbed();
   }

   private void OnFrobbing()
   {
      var handler = Frobbing;
      if (handler != null)
         handler(this, new FrobbingEventArgs());
   }

   private void OnFrobbed() …
Run Code Online (Sandbox Code Playgroud)

c# events contravariance

1
推荐指数
1
解决办法
1303
查看次数