【问题标题】:Filter with terniary operator使用三元运算符过滤
【发布时间】:2020-06-02 18:01:16
【问题描述】:

我有一个方法

AddOrUpdateList(this List<T> list, T scope, Func<T, bool>, Func<T, bool> when = null){
    T item = default;
    if (when == null)
        list.SingleOrDefault(t => t.Equals(scope)); //Check Single
    else
        item = list.SingleOrDefault(when);
    .
    .
    .
}

当我要使用它时,我有两个可能的开始:

  1. 我收到一个element,其中element.Title 是什么东西,所以我使用Title 作为过滤器
  2. 我收到了一个没有标题的element,所以我需要从列表中获取最后一个

我正在考虑使用三元运算符和 lambda 来创建一个考虑这两种情况的过滤器。

我想出的是:

var filter = (element.Title != "")
   ? (Func<T, bool>)(e => e.Title == element.Title)
   : (Func<T, bool>)(e = list.Select(ele => ele).Last());

但这给了我:Error CS0030 Cannot convert type 'T' to 'System.Func&lt;T, bool&gt;'

您有什么想法或帮助可以给我吗??

我对 C# 和 Linq 很陌生,所以我不太了解某些事情应该如何工作

提前致谢。

【问题讨论】:

  • e = list -- 你的意思是e =&gt; list。那说list.Select(ele =&gt; ele).Last() 毫无意义:为什么不做list.Last()(假设list 是一个布尔集合?)
  • list 是一种类型的对象列表
  • ... 那是bool 的一种吗?现在,我无法弄清楚你想要做什么。
  • 我有一种方法可以使用元素的标题作为过滤器来添加或更新现有元素。但是我有一些没有标题的元素,所以它们必须更新列表中的最后一个元素

标签: c# lambda operators


【解决方案1】:

您当前的过滤器是

var filter = (element.Title != "")
   ? (Func<T, bool>)(e => e.Title == element.Title)
   : (Func<T, bool>)(e = list.Select(ele => ele).Last());

但是e = list.Select(ele =&gt; ele).Last() 不是Func&lt;T, bool&gt;。事实上,它根本不是一个函数。正如@canton7 所说,您需要使用箭头符号(=&gt;)来创建一个 lambda。此外,即使该行是 lambda,它也将是 Func&lt;T, T&gt; 类型, 因为它只是返回类型为 T 的项目列表中的最后一项;它根本不返回布尔值!

这是你想要的更多吗?

var filter = (element.Title != "")
   ? (Func<T, bool>)(e => e.Title == element.Title)
   : (Func<T, bool>)(e => e.Title == list.Last().Title);

【讨论】:

  • 明天会检查,但我认为应该可以。谢谢
  • 我试了一下,效果很好。非常感谢
【解决方案2】:

element 是什么类型的?所以,AddOrUpdateList(Func&lt;T, bool&gt;) 使用 T 作为一些通用代码的类型。当你有具体的元素时,你应该知道什么类型的代码。并设置一个具体的类名。

如果您显示更多代码,我会尽力帮助您。

可能是我倒闭了,但这似乎很奇怪。根据方法名称,如果元素不存在则添加元素,如果元素已经在列表中,则更新它。

所以,这里有一个典型的这种方法实现的例子。

public void AddOrUpdate<T, K>(this List<T> list, T element, Func<T, K> keySelector, Action<T, T> mapFunction) : T new()
{
    var elementKey = keySelector(element);
    var elementForUpdate = list.FirstOrDefault(x => keySelector(x) == elementKey);

    var exists = elementForUpdate != null;

    if (!exists)
    {
        var newElement = new T();
        list.Add(newElement);
        elementForUpdate = list.Last();
    }

    mapFunction(elementForUpdate, element);
}

那么,在代码的其他部分你可以像这样使用它:

...
var itemToAdd = new ClassWithTitle { Title = "Title 1"};
list.AddOrUpdate(itemToAdd , x => x.Title, (destination, origin) =>
{
    //Logic to map fields
    destination.Title = origin.Title;
    destination.SomeOtherField = origin.SomeOtherField;
})
...

请注意。

还有一个选项,如果你使用列表(而不是数据库),你可以使用方法IndexOf(),那么这个方法将非常简单。

public void AddOrUpdate<T, K>(this List<T> list, T element, Func<T, K> keySelector)
{
    var elementKey = keySelector(element);
    var elementFounded = list.FirstOrDefault(x => keySelector(x) == elementKey);

    var exists = elementForUpdate != null;

    if (!exists)
    {
        //IMPORTANT: Here you add element that sended to method. You should take it into consideration. 
        //If you want to add a clone of this object, implement interface IClonable and use this method like   list.Add(element.Clone());
        list.Add(element);
        return;
    }

    var indexOfFoundedElement = list.IndexOf(elementFounded);

     //IMPORTANT: Here you replace element that sended to method. You should take it into consideration. 
    list[indexOfFoundedElement] = element;
}

【讨论】:

  • 这个更适合作为评论
  • 元素属于 T 类型,因为它取决于我调用该方法的位置。基本上我有各种包含对象的列表。每个列表都来自一种不同的类型,因此方法必须是 T,以订购我拥有的各种列表。我更新了问题以显示更多内容
猜你喜欢
  • 2020-09-17
  • 2013-06-11
  • 2014-12-12
  • 2020-03-14
  • 2023-03-05
  • 1970-01-01
  • 2018-09-10
相关资源
最近更新 更多