代码之家  ›  专栏  ›  技术社区  ›  Moe Sisko

尝试将多个函数返回的“外观相似”元组映射到一个变量

c#
  •  0
  • Moe Sisko  · 技术社区  · 4 年前

    假设有一个具有此表单代码的库:

     public class SomeLib
    {
        public (bool WasOk, string Message) DoCheck(string fileName)
        {
            // do something here to check the file. 
            return (true, "all good");
        }
    
        public (bool WasOk, string Message) DoCheck(byte[] fileBytes)
        {
            // do something here to check the file as bytes 
            return (true, "all good");
        }
    }
    

    使用此库的代码如下所示:

        int option = 1;
    
        SomeLib lib = new SomeLib();
    
        if (option == 0)
        {
            var res1 = lib.DoCheck("hello");
            MessageBox.Show(res1.WasOk + res1.Message);
        }
        else
        {
            var res2 = lib.DoCheck(new byte[] { });
            MessageBox.Show(res2.WasOk + res2.Message);
        }
    

    我希望做的是将对DoCheck的两个调用返回的值存储到一个公共变量中。例如。:

        int option = 1;
    
        SomeLib lib = new SomeLib();
    
        var res; // doesn't compile, obviously
    
        if (option == 0)
        {
            res = lib.DoCheck("hello");                
        }
        else
        {
            res = lib.DoCheck(new byte[] { });
        }
    
        MessageBox.Show(res.WasOk + res.Message);  // act on the result in the same way for both branches. 
    

    我希望这是有意义的。我想做的事可能吗?假设库中的代码不能更改。

    1 回复  |  直到 4 年前
        1
  •  3
  •   Caius Jard    4 年前

    var res 没有编译,因为它没有任何类型信息。如果要编写声明变量的语句,编译器必须能够从左侧或右侧以某种方式计算出类型:

    StringBuilder sb = new StringBuilder(); //both sides, available from the dawn of time
    var sb = new StringBuilder();           //for a long time
    StringBuilder sb = new();               //more recently
    

    如果没有右侧,则左侧必须具有类型信息:

    StringBuilder sb;
    

    因此,对于您的案例,您需要将类型信息放在左侧。您甚至可以重命名成员(但不必重命名)

    (bool AllGood, string Note) res;
    
    (bool WasOk, string Message) res;
    
    (bool, string) res;  //access the bool in res.Item1, string in res.Item2
    

    你可以用一个三元数来表示:

    var res = (option == 0) ? lib.DoCheck(hello) : lib.DoCheck(new byte[] { });
    

    这两个方法都返回具有相同命名成员的元组,因此 res 将会有 res.WasOk 和 res.Message 所以它被编译成这样:

    (bool WasOk, string Message) res = ...
    

    如果出现的元组中的方法具有不同的名称,它仍会像这样编译:

    (bool, string) res = ...
    

    您仍然可以通过Item1和Item2访问数据


    如果您使用这种三元方法,那么您也可以解构元组,这也允许您重命名:

    var(allGood, note) = ... ? ... : ... ;
    
    MessageBox.Show(note);
    

    而不是一个元组变量 res.Whatever ,这创建了两个变量,就像您这样做一样:

    var res = ... ? ... : ... ;
    var allGood = res.WasOk;
    var note = res.Message;
    

    有很多处理元组的选项。。

        2
  •  1
  •   thisisnabi    4 年前

    必须初始化隐式类型的局部变量

    隐式类型的局部变量必须在声明的同时用值初始化。 here

    要更正此错误

    为变量赋值或为其指定显式类型。

    (bool AllGood, string Note) res;