【问题标题】:Common problem for me in C#, is my solution good, stupid, reasonable? (Advanced Beginner)我在 C# 中的常见问题,我的解决方案是好、愚蠢、合理的吗? (高级初学者)
【发布时间】:2009-03-15 23:01:57
【问题描述】:

好的,知道我来自 Cold Fusion,所以我倾向于以 CF 的方式思考问题,而 C# 和 CF 在一般方法中是不同的。

所以问题是:我想通过 LINQ 从 SQL 数据库中提取数据的“表”(我就是这么想的),然后我想在内存中对其进行一些计算。这个“表”包含 6 或 7 个不同类型的值。

现在,我的解决方案是使用自定义类型的通用列表进行 LINQ 查询。所以我的例子是 RelevanceTable。我提取了一些数据,我想对数据进行一些评估,这些数据首先以 .Contains 开头。看来 .Contains 想要对整个列表采取行动,或者什么都不做。因此,如果我有List<string>,我可以使用它,但如果我有List<ReferenceTableEntry>,其中 ReferenceTableEntry 是我的自定义类型,我需要重写 IEquatable 并告诉编译器“Equals”到底是什么意思。

虽然这似乎不无道理,但要解决一个简单的问题似乎还有很长的路要走,所以我暗自怀疑我的方法从一开始就有缺陷。

如果我想使用 LINQ 和 .Contains,重写接口是唯一的方法吗?似乎只有一种方法可以说明要在哪个字段上进行操作。除了 LIST 之外,是否还有另一种可能具有这种能力的集合类型。为此,我已经开始大量使用 List,虽然我看了又看,但还是看到了一些其他但不一定更好的方法。

我不是在寻找性能或紧凑性或可读性的一些优点,只是想知道我是否在六角螺丝中使用十字螺丝刀。如果我的方法是“体面”的方法,但不是最好的,我当然想知道更好的方法,但只要知道它在球场上就会给我一点“是的!我不傻!”在切换到另一种方法之前,我至少会完成我正在做的事情。

希望我解释得足够好。谢谢你的帮助。

【问题讨论】:

  • 高级初学者是在中级之前还是之后? =p

标签: c# linq-to-sql collections


【解决方案1】:

您究竟想对桌子做什么?目前还不清楚。但是,标准 LINQ (-to-Objects) 方法将可用于任何类型的集合(包括List<T>),允许WhereFirstAnyAll 等的任何范围。

那么:你想做什么?如果你有这张桌子,你想要什么值?

作为一个猜测(基于Contains 的东西) - 你只是想要:

bool x= table.Any(x=>x.Foo == foo); // or someObj.Foo

?

【讨论】:

    【解决方案2】:

    List 类中的一些方法有重载,它们接受一个委托(可选地以 lambda 表达式的形式),您可以使用它来指定要查找的字段。

    例如,查找 Id 属性为 42 的项目:

    ReferenceTableEntry found = theList.Find(r => r.Id == 42);
    

    found 变量将引用第一个匹配的项目,如果没有匹配的项目,则为 null

    还有一些接受委托或表达式的 LINQ 扩展。这将与Find 方法相同:

    ReferenceTableEntry found = theList.FirstOrDefault(r => r.Id == 42);
    

    【讨论】:

      【解决方案3】:

      好的,所以如果我没看错,你想使用 contains 方法。将它与对象集合(例如 ReferenceTableEntry)一起使用时,您需要小心,因为您要检查集合是否包含与您要比较的对象相同的对象。

      如果您使用 .Find() 或 .FindAll() 方法,您可以使用匿名方法指定要匹配的条件。

      例如,如果您想在列表中查找 ID 大于 1 的所有 ReferenceTableEntry 记录,您可以执行以下操作

      List<ReferenceTableEntry> listToSearch = //populate list here
      var matches = listToSearch.FindAll(x => x.Id > 1);
      

      matches 将是 ID 大于 1 的 ReferenceTableEntry 记录的列表。

      说了这么多,还不完全清楚这就是你想要做的。

      【讨论】:

      • 我要补充一点,在使用 Contains 时,集合使用 .Equals 方法来测试相等性。此外,值类型当然不会测试引用相等性。
      【解决方案4】:

      这是创建我正在谈论的对象所涉及的 LINQ 查询,问题行是:

      .Where (searchWord => queryTerms.Contains(searchWord.Word))

      List<queryTerm> queryTerms = MakeQueryTermList();
      
      public static List<RelevanceTableEntry> CreateRelevanceTable(List<queryTerm> queryTerms)
                  {
                  SearchDataContext myContext = new SearchDataContext();
                  var productRelevance = (from pwords in myContext.SearchWordOccuranceProducts
                  where (myContext.SearchUniqueWords
                  .Where (searchWord => queryTerms.Contains(searchWord.Word))
                  .Select (searchWord => searchWord.Id)).Contains(pwords.WordId)
                  orderby pwords.WordId
                  select new {pwords.WordId, pwords.Weight, pwords.Position, pwords.ProductId});
                  }
      

      此查询返回与提交的搜索字符串匹配的 WordId 列表(当它是 List 并且它只是单词时,这很好,因为作为前面提到的回答者,它们是相同类型的对象)。我的自定义类型这里是 queryTerms,一个包含 WordId、ProductId、Position 和 Weight 的 List。从那里我开始通过对创建的对象进行各种操作来计算相关性。按产品对“权重”求和,使用位置匹配来提高权重等。我要保持这一点的是,执行这些操作的规则会改变,但所涉及的基本因素不会改变。我什至希望它更加独立(我还在学习,我不想花哨),但是当我这样做时,本地和解释 LINQ 查询的规则似乎让我感到困惑。

      由于 CF 一直支持查询查询,这就是我倾向于采用的方式。从数据库中提取您需要的数据,然后在内存表上执行您的操作(包括使用聚合函数的查询)。

      我希望这样可以更清楚。

      【讨论】:

      • 所以我认为通过重新阅读答案并返回并在通用集合上进行更多阅读,我认为我确实验证了我的方法至少是可行的,并且我确实需要覆盖 List 的默认方法做一些适合我的类型的事情。我也学会了下次问一个更好的问题。
      猜你喜欢
      • 2022-11-03
      • 1970-01-01
      • 2015-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-24
      相关资源
      最近更新 更多