匿名方法的丑陋之处和优点-C#

发布于 2024-08-26 22:13:50 字数 666 浏览 4 评论 0原文

我被要求解释一下匿名方法的丑陋之处和优点。

我解释了可能

丑陋的事情

anonymous methods turning quickly into spaghetti code.

优点

我们可以使用匿名方法生成线程安全代码:示例

static List<string> Names = new List<string>(
  new string[] {
    "Jon Skeet",
    "Marc Gravell",
    "David",
    "Bill  Gates"
  });

static List<string> FindNamesStartingWith(string startingText)
{
  return Names.FindAll(
    delegate(string name)
    {
      return name.StartsWith(startingText);
    });
}

但实际上我不知道它是否是线程安全的。我被要求证明合理性它。 任何人都可以帮助我理解吗 (1)匿名方法的优点 (2)上面的代码是否线程安全?

I was asked to explain the ugly thing and advantages of anonymous method.

I explained possibly

Ugly thing

anonymous methods turning quickly into spaghetti code.

Advantages

We can produce thread safe code using anonymous method :Example

static List<string> Names = new List<string>(
  new string[] {
    "Jon Skeet",
    "Marc Gravell",
    "David",
    "Bill  Gates"
  });

static List<string> FindNamesStartingWith(string startingText)
{
  return Names.FindAll(
    delegate(string name)
    {
      return name.StartsWith(startingText);
    });
}

But really i did not know whether it is thread safe or not.I was asked to justify it.
Can any one help me to understand
(1) advantages of anonymous methods
(2) Is the above code thread safe or not?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

独夜无伴 2024-09-02 22:13:50

嗯,“线程安全”是一个相当广泛的术语。您正在考虑哪种多线程使用?如果没有任何内容写入列表,我期望它是安全的,没有任何数据损坏或异常...

现在,至于匿名方法的“丑陋”...您使用的是 C# 3 吗?如果是这样,请开始使用 lambda 表达式,它通常更简洁:

static List<string> FindNamesStartingWith(string startingText)
{
    return Names.FindAll(name => name.StartsWith(startingText));
}

或者,使用 LINQ:

static List<string> FindNamesStartingWith(string startingText)
{
    return Names.Where(name => name.StartsWith(startingText)).ToList();
}

或者,如果您不一定需要列表:

static IEnumerable<string> FindNamesStartingWith(string startingText)
{
    return Names.Where(name => name.StartsWith(startingText));
}

或者,如果您更喜欢查询表达式:

static IEnumerable<string> FindNamesStartingWith(string startingText)
{
    return from name in names
           where name.StartsWith(startingText)
           select name;
}

对我来说,这些都不像意大利面条代码。然而,如果你想问是否应该使用这个或其他东西,你真的应该提出一个替代方案。这是一个简单的问题:

static List<string> FindNamesStartingWith(string startingText)
{
    List<string> ret = new List<string>();
    foreach (string name in Names)
    {
        if (name.StartsWith(startingText))
        {
            ret.Add(name);
        }
    }
    return ret;
}

你觉得这样更清楚了吗?如果是这样,那很好 - 但我怀疑只是你不太熟悉匿名函数、LINQ等。正如你所看到的,代码明显多了 - 我肯定需要更长的时间来检查与任何早期的样本相比,它做了正确的事情。

Well, "thread safe" is a pretty broad term. What sort of multi-threaded use are you thinking of? I'd expect it to be safe without any data corruption or exceptions if nothing's writing to the list...

Now, as for the "ugliness" of anonymous methods... are you using C# 3? If so, start using lambda expressions, which are generally cleaner:

static List<string> FindNamesStartingWith(string startingText)
{
    return Names.FindAll(name => name.StartsWith(startingText));
}

Alternatively, using LINQ:

static List<string> FindNamesStartingWith(string startingText)
{
    return Names.Where(name => name.StartsWith(startingText)).ToList();
}

Or if you don't necessarily need a list:

static IEnumerable<string> FindNamesStartingWith(string startingText)
{
    return Names.Where(name => name.StartsWith(startingText));
}

Or if you prefer a query expression:

static IEnumerable<string> FindNamesStartingWith(string startingText)
{
    return from name in names
           where name.StartsWith(startingText)
           select name;
}

None of these look like spaghetti code to me. However, if you're going to ask whether you should use this or something else, you should really put forward an alternative. Here's a simple one:

static List<string> FindNamesStartingWith(string startingText)
{
    List<string> ret = new List<string>();
    foreach (string name in Names)
    {
        if (name.StartsWith(startingText))
        {
            ret.Add(name);
        }
    }
    return ret;
}

Do you find that clearer? If so, that's fine - but I suspect it's just that you're not really familiar with anonymous functions, LINQ etc. As you can see, there's significantly more code - it would definitely take me longer to check that that does the right thing than any of the earlier samples.

何其悲哀 2024-09-02 22:13:50

好吧,这完全取决于线程安全的含义。

如果在执行 FindAll 期间,其他某个线程更改了底层 Names 集合,那么您可能会得到奇怪的结果。

在多个线程上多次调用 FindAll 本身是否安全(即仅执行它们)?是的,这是肯定的。

至于匿名方法的优点,请考虑替代方案。

您想要:

  1. 查找集合中的某些项目
  2. 知道您想要查找哪个项目的唯一方法是计算每个项目的某个表达式

您可以这样做:

List<string> result = new List<string>();
foreach (string name in Names)
    if (name.StartsWith(startingText))
        result.Add(name);
return result;

或者,给定新的 lambda 语法,你可以这样做:

return Names.FindAll(name => name.StartsWith(startingText));

我知道我更喜欢哪个,但他们做不同的事情,得到相同的结果(在本例中)。

在第一种情况下,你自己执行所有代码,没有魔法。

在第二种情况下,您为 FindAll 提供了一种方法来确定将哪些项目放入结果中。在这种情况下,没有不可执行的方法可以做到这一点,您需要让 FindAll 为每个项目执行您指定的一些代码。

Well, it all depends on what you mean by thread-safe.

If, during the execution of FindAll, some other thread changes the underlying Names collection, then you might get odd results.

Is multiple calls to FindAll on multiple threads safe by themselves, that is, with only them executing? Yes, that's a definite yes.

As for the advantages of anonymous methods, consider the alternative.

You want to:

  1. Find some item of the collection
  2. The only way to know which item you want to find is to evaluate some expression for each one

You could do it like this:

List<string> result = new List<string>();
foreach (string name in Names)
    if (name.StartsWith(startingText))
        result.Add(name);
return result;

or, given the new lambda syntax, you could do it like this:

return Names.FindAll(name => name.StartsWith(startingText));

I know which one I prefer, but they do different things, with the same result (in this case.)

In the first case, you execute all the code yourself, there's no magic.

In the second case, you give to FindAll a way to figure out which items to put into the result. There is no non-executable way to do that in this case, you need to have FindAll execute some code, that you specify, for each item.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文