首页 > 解决方案 > 将 Linq 代码从 VB.Net 转换为 C#(组加入)

问题描述

我必须将以下表达式从 VB.NET 转换为 C#:

            Dim query = (From egyosztaly As UpdateItemBase In UpdateItemCollectionRemote
                     Group Join egystudent As UpdateItemBase In UpdateItemCollectionLocal On egyosztaly.HashCode Equals egystudent.HashCode
                     Into csoport = Group
                     From egycsoportelem In csoport.DefaultIfEmpty
                     Select New ComparedUpdateItem With {.Remote = egyosztaly, .Local = egycsoportelem}).ToList()

我的尝试:

            var query = (from egyosztaly in UpdateItemCollectionRemote
                     join egystudent in UpdateItemCollectionLocal on egyosztaly.HashCode equals egystudent.HashCode into csoport
                     from egycsoportelem in csoport.DefaultIfEmpty
                     select new ComparedUpdateItem() { Remote = egyosztaly, Local = egycsoportelem }).ToList();

C# 无法理解第二个“来自”部分。

感谢帮助!

标签: c#vb.net

解决方案


在 C# 中,当您调用不带参数的方法时需要显式地提供空括号。没有括号的标识符通常被认为是属性,而不是方法(vb 命名法中的函数)

var query = (
    from egyosztaly in UpdateItemCollectionRemote
    join egystudent in UpdateItemCollectionLocal on egyosztaly.HashCode equals egystudent.HashCode into csoport
    from egycsoportelem in csoport.DefaultIfEmpty() 
    select new ComparedUpdateItem() { 
      Remote = egyosztaly, 
      Local = egycsoportelem 
    }
  ).ToList();

DefaultIfEmpty是一个方法,你想调用它,所以你需要添加()


在 VB 中,开发人员通常并不真正关心我们在 C# 中关心的同一组事情。在 C# 中,我们非常关心命名和大小写等问题:

class SomeName{                                    //class names PascalCase
  private int _someInt;                            //private vars camelCase, usually underscore led
  public int SomeInt { get { return _someInt; } }  //public properties PascalCase

  public void SomeMethod(int someArgument){        //methods PascalCase, arguments camelCase
    void localFunction() { ... };                  //local function, usually camelCase
    int localVariable = 0;                         //local vars camelCase

    SomeStaticClass.SomeMethodWithNoArgs();        //Static classes PascalCase, method calls with no args must include ()
    someInstance.SomeMethod(1);                    

    var x = new Thing { X = 1 };                   //new calling default constructor no longer requires () if initializing properties
    Thing x = new();                               //but does if new stands alone   
  }
}

最终,通常可以查看一些代码并仅从外壳中知道发生了什么;唯一一次变得朦胧是在这样的场景中:

AddAction(Foo.SomeThing)  //AddAction is a method that takes.. er..

Foo.SomeThing这里可能是一个名为 Foo 的实例的属性,也可能是一个名为 Foo 的类型的方法 - 当我们调用一个将方法(委托)作为参数的方法时,我们传递的方法名称不带()- put()会调用方法并传递结果

AddAction(Foo.SomeThing)   //SomeThing could be a property or a method
AddAction(Foo.SomeThing()) //SomeThing is a method, called and its return value passed to AddAction

在最新的 VS 属性和方法中,颜色不同,这有助于解决这种情况。对于您拥有“采用方法的方法”的用例,您会在 LINQ 中遇到很多这样的情况,但我将使用 List 举一个示例:

var strings = new List<string>() {"hello","world"};

strings.ForEach(Console.WriteLine);

ForEach 是一个接受方法参数的方法。List 将遍历自身,为每个项目调用一次提供的方法。传递的方法必须接受一个字符串作为参数,就像 Console.WriteLine 一样。列表中的所有字符串都将打印到控制台。传递方法名不带 是合法的,()因为我们不想调用 WriteLine 方法并将结果传递给 ForEach(实际上 WriteLine 没有结果);我们想将WriteLine 方法本身传递给 ForEach

同样,此语法“创建一个迷你方法”:

x => something_here;

所以这也是合法的:

strings.ForEach(x => Console.WriteLine(x.ToUpper()));

整个x => Console.WriteLine(x.ToUpper())事情是“一个采用名为 x 的参数的方法,其类型将从 ForEach 的签名中推导出来,对于字符串列表来说,它是‘采用单个字符串参数的方法’”。在 VB 中等价于:

strings.ForEach(Function(x) Console.WriteLine(x.ToUpper));

(当然 VB 不会在意如果是ToUpperToUpper()但 C# 的人非常关心这些细节,因为它有助于理解程序并获得关于什么是什么的线索):)


推荐阅读