如果为 null,则 Lambda 表达式返回零

发布于 2024-10-09 10:02:22 字数 469 浏览 4 评论 0原文

在我的 WPF 应用程序中,我曾经将控件动态添加到 Canvas 中。控件的名称格式为“Control_UniqueValue”。

即,如果我将第一个控件添加到画布,那么名称将是“Control_1”,下一个将是“Control_2”等...

我的要求是获取添加的控件的最大值,

我使用了以下语句

string maxId = (string)canvas1.Children.Cast<FrameworkElement>().ToList().Max(x => (x.Name.Substring(x.Name.LastIndexOf('_') + 1)));

但这里的问题是

  1. 需要将值返回为int

  2. 如果画布不包含控件,则会引发错误(尝试使用Nullable类型,但失败)

in my WPF application i used to add controls dynamically to a Canvas. The name format of the control is "Control_UniqueValue".

i.e., if i add first control to the canvas, then the name will be "Control_1" and the next will be "Control_2" etc...

my requirement is to get the max value of the added controls

i used the following statement for that

string maxId = (string)canvas1.Children.Cast<FrameworkElement>().ToList().Max(x => (x.Name.Substring(x.Name.LastIndexOf('_') + 1)));

but the problem here is

  1. need to return the value as int

  2. if the canvas contains no controls it will raise error (tried using Nullable type, but failed)

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

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

发布评论

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

评论(4

无力看清 2024-10-16 10:02:22
int  maxId = canvas1.Children
    .Cast<FrameworkElement>()
    .Select(e => int.Parse(e.Name.Substring(e.Name.LastIndexOf('_'))))
    .DefaultIfEmpty()
    .Max();

如果序列中没有元素,则应返回 0,而不是引发异常。此外,不需要在代码中调用 ToList。如果任何控件名称不符合预期格式,这仍然会引发异常。

int  maxId = canvas1.Children
    .Cast<FrameworkElement>()
    .Select(e => int.Parse(e.Name.Substring(e.Name.LastIndexOf('_'))))
    .DefaultIfEmpty()
    .Max();

This should return 0 instead of throwing an exception if there are no elements in the sequence. Also, the call to ToList in your code is not required. This will still throw an exception if any of the control names are not in the expected format.

旧梦荧光笔 2024-10-16 10:02:22

要获取整数,您可以使用 int.Parse 方法。您不必调用 ToList()

没有错误检查,因此您的控件必须根据您的规则 name_id 进行命名。

如果序列为空,您可以使用 DefaultIfEmpty 扩展方法提供默认值:

int maxId = canvas1.Children
             .Cast<FrameworkElement>()
             .DefaultIfEmpty(new FrameworkElement() { Name = "Control_0" })
             .Max(x => (int.Parse(x.Name.Split('_')[1]) + 1)));

To get an integer, you might use the int.Parse method. You don't have to call ToList().

There is no error checking, so your controls have to named regarding to your rule name_id.

You can use the DefaultIfEmpty extension method to provide a default value, if the sequence is empty:

int maxId = canvas1.Children
             .Cast<FrameworkElement>()
             .DefaultIfEmpty(new FrameworkElement() { Name = "Control_0" })
             .Max(x => (int.Parse(x.Name.Split('_')[1]) + 1)));
戒ㄋ 2024-10-16 10:02:22

由于 Max() 要求其序列中至少有一个元素,因此您必须

  • 捕获异常并将 max 设置为零,
  • 然后在调用 Max() 之前检查长度。 我建议这样做

虽然可以在一个长查询表达式中编写逻辑,但我建议您将其分解一点以提高可读性。创建一个返回子控件名称的整数部分的方法:

private int NumberFromElementName(string name)
{
    // Or search for the last '_' using name.LastIndexOf()
    var numString = name.Substring("Control_".Length);
    return Int32.Parse(numString);
}

然后分两步执行查询,以便您查看返回序列的长度。请注意,我将其转换为数组以避免运行查询两次。我还使用 OfType 扩展方法,这样即使画布有一个不是 FrameworkElement 类型的子元素。

var children = canvas1.Children.OfType<FrameworkElement>().ToArray();
int max = 0;
if (children.Length > 0)
    max = children.Max(x => NumberFromElementName(x.Name));
string nextChildName = String.Format ("Control_{0}", max + 1);

编辑:正如@Jan在他的回答中指出的,您可以使用 DefaultIfEmpty 在查询中的 Max 调用之前。

Since Max() requires at least one element in its sequence you either have to

  • catch the exception and set max to zero
  • check the length before calling Max(). I'd recommend this

While it is possible to write the logic in one long query expression, I'd recommend you break it up a bit to improve readability. Create a method that returns the integer part of a child control's name:

private int NumberFromElementName(string name)
{
    // Or search for the last '_' using name.LastIndexOf()
    var numString = name.Substring("Control_".Length);
    return Int32.Parse(numString);
}

Then do the query in two steps to allow you to look at the length of the returned sequence. Notice I convert it to an array to avoid having to run the query twice. I'm also using the OfType extension method so that it works even if the canvas has a child which isn't of type FrameworkElement.

var children = canvas1.Children.OfType<FrameworkElement>().ToArray();
int max = 0;
if (children.Length > 0)
    max = children.Max(x => NumberFromElementName(x.Name));
string nextChildName = String.Format ("Control_{0}", max + 1);

EDIT: As pointed out by @Jan in his answer, you can avoid splitting the query in two parts by using the DefaultIfEmpty before the Max call in the query.

银河中√捞星星 2024-10-16 10:02:22

得到了最终答案

int maxId = canvas1.Children .Cast<FrameworkElement>() .Select(e => int.Parse(e.Name.Substring(e.Name.LastIndexOf('_')+ 1))) .DefaultIfEmpty() .Max(x => x + 1); 

谢谢Jan &李

got the final answer

int maxId = canvas1.Children .Cast<FrameworkElement>() .Select(e => int.Parse(e.Name.Substring(e.Name.LastIndexOf('_')+ 1))) .DefaultIfEmpty() .Max(x => x + 1); 

Thanks Jan & Lee

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