0

目前,我有一个像这样的静态工厂方法:

public static Book Create(BookCode code) {
    if (code == BookCode.Harry) return new Book(BookResource.Harry);
    if (code == BookCode.Julian) return new Book(BookResource.Julian);
    // etc.
}

我不以任何方式缓存它们的原因是因为 BookResource 对文化很敏感,这可能会在调用之间发生变化。文化的变化需要反映在归还的书籍对象中。

执行这些 if 语句可能会成为速度瓶颈。但是如果我们将书籍代码映射到匿名函数/委托呢?类似于以下内容:

delegate Book Create();
private static Dictionary<BookCode, Delegate> ctorsByCode = new Dictionary<BookCode, Delegate>();
// Set the following somewhere
// not working!
ctorsByCode[BookCode.Harry] = Create () => { return new Book(BookResource.Harry); }
// not working!
ctorsByCode[BookCode.Julian] = Create () => { return new Book(BookResource.Julian); } 
public static Book Create(BookCode code) {
    return (Book)ctorsByCode[code].DynamicInvoke(null);
}

我怎样才能让这些Create() => {线条真正起作用?

当有 <50 个书本代码(因此 <50 个 if 语句)时,这在速度方面值得吗?

这是一个类似的问题,但不幸的是,作者没有发布他的代码Enum,Delegate Dictionary collection where delegate 指向一个重载的方法

更新

做了一些性能基准 ifs vs delegates。我随机选择了单元代码,并为这两种方法使用了相同的种子。委托版本实际上稍微慢一些。这些代表正在造成某种开销。我使用发布版本进行运行。

5000000 iterations
CreateFromCodeIf ~ 9780ms
CreateFromCodeDelegate ~ 9990ms
4

3 回答 3

2

像这样:

private static readonly Dictionary<BookCode, Func<Book>> ctorsByCode = new Dictionary<BookCode, Func<Book>>();

...

ctorsByCode[BookCode.Harry] = () => new Book(BookResource.Harry);

public static Book Create(BookCode code) {
    return ctorsByCode[code]();
}

Func<Book>类型是预定义的泛型委托类型,您可以使用它而不是创建自己的。
此外,您的字典必须包含特定的委托类型,而不是基Delegate类。

尽管 lambda 表达式是无类型表达式,但它们可以在需要委托类型的地方使用(例如您的索引器分配),并且会隐式假定委托的类型。

你也可以写

ctorsByCode[BookCode.Harry] = new Func<Book>(() => new Book(BookResource.Harry));

我建议您将字典更改为包含BookResources ,如下所示:

private static readonly Dictionary<BookCode, BookResource> codeResources = new Dictionary<BookCode, BookResource>();

...

codeResources[BookCode.Harry] = BookResource.Harry;

public static Book Create(BookCode code) {
    return new Book(codeResources[code]);
}
于 2010-08-29T01:47:54.250 回答
2

坦率地说,您可能不会注意到两者之间的性能差异。但是,如果您要使用“功能”版本,我不会只使用泛型Delegate,而是传递您刚刚创建的委托。所以这将是你的(更简单的)代码:

delegate Book Create();
private static Dictionary<BookCode, Create> ctorsByCode 
    = new Dictionary<BookCode, Create>();

ctorsByCode[BookCode.Harry] = () => new Book(BookResource.Harry);
ctorsByCode[BookCode.Julian] = () => new Book(BookResource.Julian); 

public static Book Create(BookCode code) {
    return ctorsByCode[code]();
}
于 2010-08-29T01:51:37.403 回答
0

randomguy,你为什么把事情弄得这么复杂?有两种方法可以避免您的问题和随后的答案中出现这种混乱。

  1. BookResource bookResourceEnum = (BookResource)Enum.Parse(typeof(BookResource),bookCode);

    返回新书(bookResourceEnum);

  2. 或者更好的是,让你的静态工厂方法 Create 接受 BookResource 而不是 BookCode,并让客户担心从代码到枚举的转换,这样没有人可以传入无法映射到 BookResource 的代码。

说真的,如果你给我写了一个包含 50 个“如果”或更糟糕的是有 50 个“代表”的代码,我们就会进行“谈话”。当你不确定这是你的瓶颈时,尽量避免过早的优化(如果有的话)。可读性和可维护性应该是第一位的。

于 2010-08-30T13:21:21.177 回答