gpt4 book ai didi

c# - 效率 : Func, 与 T 的实例

转载 作者:太空狗 更新时间:2023-10-30 00:43:33 24 4
gpt4 key购买 nike

最近我一直在尝试使用 Func<T>类,到目前为止我很喜欢它。然而,我注意到我越来越多地开始使用它,而不是实际使用 T 的实例。 ,所以想问一下; 使用Func<T> 的开销是多少?对比T ? 我知道这是一个有点笼统的问题,因为 T可以是任何东西,所以我想这个问题应该集中在传递一个函数而不是一个简单对象的实例的开销是多少?

为了论证,我们假设如下。

我们的模拟对象,T

public class Person
{
private string _name = string.Empty;
private int _age = 0;
private bool _isMale = true;

public Person(string name, int age, bool isMale)
{
this.Name = name;
this.Age = age;
this.IsMale = isMale;
}

public string Name
{
get { return this._name; }
set { this._name = value; }
}

public int Age
{
get { return this._age; }
set { this._age = value; }
}

public bool IsMale
{
get { return this._isMale; }
set { this._isMale = value; }
}
}

现在,假设我们在 IDictionary 上有一个漂亮的扩展方法,即通过键选择值,默认值。伪代码可以描述如下:
是在 KeyValuePair 集合中找到的键 是的,返回值否,返回默认

选项 1. 我们的扩展方法使用 T 的实例

public static TValue GetValueOrDefault<TKey, TValue>(this IDictionary source, TKey key, TValue @default)
{
if (source.ContainsKey(key))
{
return source[key];
}
return @default;
}

// usage
var myValue = myDictionary.GetValueOrDefault("Richard", new Person());

选项 2。我们的扩展方法使用 Func<T> ...嗯,漂亮!

public static TValue GetValueOrDefault<TKey, TValue>(this IDictionary source, TKey key, Func<TValue> defaultSelector)
{
if (source.ContainsKey(key))
{
return source[key];
}
return defaultSelector();
}

// usage
var myValue = myDictionary.GetValueOrDefault("Richard", () => new Person("Richard", 25, true));

比较

比较上述选项,很明显两者都有潜在的好处。选项 1 稍微更容易阅读,但我目前喜欢 Func<T> 的用法,因此对我来说选项 2 似乎是理想的。我想我正在考虑它是一个延迟实例化的参数,它只在需要时执行,因此节省了效率,但我是对的吗?

最佳答案

这是我用于基准测试的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;

namespace ConsoleApplication3
{
using System.Collections;
using System.Diagnostics;
using System.Globalization;
using System.Numerics;
using System.Xml.Linq;

public class Program
{

public class Person
{
private string _name = string.Empty;

private int _age = 0;

private bool _isMale = true;

public Person(string name, int age, bool isMale)
{
this.Name = name;
this.Age = age;
this.IsMale = isMale;
}

public string Name
{
get
{
return this._name;
}
set
{
this._name = value;
}
}

public int Age
{
get
{
return this._age;
}
set
{
this._age = value;
}
}

public bool IsMale
{
get
{
return this._isMale;
}
set
{
this._isMale = value;
}
}
}

private static void Main(string[] args)
{
var myDictionary = new Dictionary<string, Person>();
myDictionary.Add("notRichard", new Program.Person("Richard1", 26, true));
myDictionary.Add("notRichard1", new Program.Person("Richard2", 27, true));
myDictionary.Add("notRichard2", new Program.Person("Richard3", 28, true));
myDictionary.Add("notRichard3", new Program.Person("Richard4", 29, true));
// usage
Stopwatch sw = new Stopwatch();
sw.Start();
for(int i = 0; i < 100000000; i++)
{
var myValue = myDictionary.GetValueOrDefault("Richard", new Program.Person("Richard", 25, true));
}
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);
sw = new Stopwatch();
sw.Start();
for (int i = 0; i < 100000000; i++)
{
var myValue = myDictionary.GetValueOrDefault("Richard", ()=> new Program.Person("Richard", 25, true));
}
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);
Console.ReadKey();
}
}
public static class Ex
{
public static TValue GetValueOrDefault<TKey, TValue>(this Dictionary<TKey, TValue> source, TKey key, TValue @default)
{
if (source.ContainsKey(key))
{
return source[key];
}
return @default;
}
public static TValue GetValueOrDefault<TKey, TValue>(this Dictionary<TKey, TValue> source, TKey key, Func<TValue> defaultSelector)
{
if (source.ContainsKey(key))
{
return source[key];
}
return defaultSelector();
}


}
}

调用每个扩展方法 100000000 次(没有找到入口,因此导致每次都执行 Func)给出以下结果:

T - 10352 毫秒

Func<T> - 12268 毫秒

调用每个扩展方法 100000000 次(并找到一个条目,因此根本不调用 Func)给出以下结果:

T - 15578 毫秒

Func<T> - 11072 毫秒

因此,哪个执行得更快取决于您保存了多少实例化以及每个实例化的成本。

通过重新使用默认的 person 实例稍微优化代码,为 T 提供 6809 毫秒和 7452 为 Func<T> :

            Stopwatch sw = new Stopwatch();
var defaultPerson = new Program.Person("Richard", 25, true);
sw.Start();
for(int i = 0; i < 100000000; i++)
{
var myValue = myDictionary.GetValueOrDefault("Richard", defaultPerson);
}
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);
sw = new Stopwatch();
sw.Start();
for (int i = 0; i < 100000000; i++)
{
var myValue = myDictionary.GetValueOrDefault("Richard", () => defaultPerson);
}

因此,理论上(如果您不考虑实例化),在调用堆栈中节省一个跃点会给您带来一些性能提升,但在实践中,这种提升可以忽略不计。

关于c# - 效率 : Func<T>, 与 T 的实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10728810/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com