【问题标题】:return multiple values in static class在静态类中返回多个值
【发布时间】:2012-07-24 23:50:34
【问题描述】:

如何在以下类中返回 FirstName 和 Surname?

public static string GetAccount(int AccountId)
{        
    LinqSqlDataContext contextLoad = new LinqSqlDataContext();

    var q = (from p in contextLoad.MyAccounts
             where p.AccountId == AccountId
             select new { Name = p.FirstName, Surname = p.Surname }).Single();

    return ??;
} 

【问题讨论】:

  • 假设您也希望返回类型正确,并且您不只是想要return string.Format("{0} {1}",q.Name,q.Surname);

标签: c# asp.net string linq return


【解决方案1】:

您可以返回强类型类、动态对象或元组。 我更喜欢返回一个强类型的类。

使用dynamic 类型的问题是你没有得到 智能感知和异常仅在运行时。

元组的问题是它没有告诉你什么 你回来。您或其他开发人员必须阅读该方法 知道什么名字和什么姓氏。

样本

public class MyResult
{
    public string Name { get; set; }
    public string Surname { get; set; }
}

public static MyResult GetAccount(int AccountId)
{        
    LinqSqlDataContext contextLoad = new LinqSqlDataContext();

    var q = (from p in contextLoad.MyAccounts
             where p.AccountId == AccountId
             select new MyResult{ Name = p.FirstName, Surname = p.Surname }).Single();

    return q;
} 

更新

我建议使用SingleOrDefault 而不是Single。这将确保您 如果 Account 不存在而不是抛出异常,则得到 null 结果。

//
select new MyResult{ Name = p.FirstName, Surname = p.Surname }).SingleOrDefault();
//

【讨论】:

  • 此代码假定查询返回一项且仅一项。如果集合中没有一个元素,Single 将引发异常。
  • 成功了!我的目标是从帐户表中获取数据,并在网页中的文本框中填写详细信息:姓名、姓氏、地址等。我得到这样的数据:FirstNameTextBox.Text = MyResults.GetAccount(AccountId).FirstName; SurnameTextBox.Text = MyResults.GetAccount(AccountId).Surname; AddressTextBox.Text = MyResults.GetAccount(AccountId).Address; . . .等等......这是使用课程的最有效方式吗?似乎每次我填写一个文本框时我都必须打电话给一个班级......有没有更好的选择?非常感谢,
【解决方案2】:

如果您不想为返回类型定义新对象,可以使用Tuple<string, string>

【讨论】:

    【解决方案3】:

    另一个(不是最好的:))选项是返回一个数组:

    public static string[] GetAccount(int AccountId)
    {        
        LinqSqlDataContext contextLoad = new LinqSqlDataContext();
    
        var q = (from p in contextLoad.MyAccounts
                 where p.AccountId == AccountId
                 select new { Name = p.FirstName, Surname = p.Surname }).Single();
    
        return new []{q.Name, q.Surname};
    } 
    

    【讨论】:

      【解决方案4】:

      通过引用传入两个对象,您可以设置它们。

      将其更改为 try 函数,作为代码味道较少的版本的示例

      public static bool TryGetAccount(int AccountId, out String FirstName, out String Surname)
      {        
          LinqSqlDataContext contextLoad = new LinqSqlDataContext();
      
          var q = (from p in contextLoad.MyAccounts
                   where p.AccountId == AccountId
                   select new { Name = p.FirstName, Surname = p.Surname }).SingleOrDefault();
      
      
          FirstName=(q==null) ? null: q.Name;
          Surname=(q==null) ? null: q.Surname;
          return q!=null;
      } 
      

      现在你可以做

      string firstName;
      string surname;
      
      if (TryGetAccount(id, out firstName,out surname)) {
        // firstName now equals the first name and surname now equals the surname
      } else {
        // Deal with value not found
      

      }

      【讨论】:

      • @the_joric 有点笼统的声明,没有任何解释,你现在让我很担心。
      • out 参数根据定义并不坏,许多编码人员认为它们是代码异味,因为它们会产生副作用。然而,它们确实有它们的用途——尤其是在 Try 风格的函数中。 See SO question
      • @BobVale 很好奇,它们怎么会产生副作用?编译器在赋值之前停止使用out 参数,调用者必须明确指定out,以便他们知道他们提供的任何变量都会被更改。副作用往往是不需要的状态更改。
      • @AdamHouldsworth 它们被认为是副作用,因为每个变量实际上都是作为对同一内存位置的引用传递给函数的,如果函数启动异步进程,则在函数返回后可能会更改该值。
      • @BobVale 谢谢,我必须记住这一点。我已经看到他们在我正在处理的当前代码库中徘徊。
      【解决方案5】:

      如果您使用的是 .Net 4,您可以返回动态而不是字符串,并直接从返回的对象中获取这两个值。

      【讨论】:

      • 仅在同一个程序集中,或者如果您使用的是 InternalsVisibleToAttribute。匿名类型是隐式“内部”的,这会导致dynamic 出现问题。
      • 这将产生涉及 DLR 的开销,因为它可以通过新类或 Tuple<string, string> 实现。此外,您还会失去 IntelliSense。
      【解决方案6】:

      如果您不介意以这种方式使用返回的类型 tuple.Item1, tuple.Item2,将其返回为 Tuples 怎么样

      【讨论】:

        【解决方案7】:

        您可以使用 Hashtable 来避免创建新的结果类。 像这样的:

          public static Hashtable GetAccount(int AccountId)
            {        
               LinqSqlDataContext contextLoad = new LinqSqlDataContext();
        
                 var q = (from p in contextLoad.MyAccounts
                 where p.AccountId == AccountId
                 select new { Name = p.FirstName, Surname = p.Surname }).Single();
        
                return new Hashtable(q.FirstName, q.Surname);
            } 
        

        你可以通过你的名字作为关键来获取姓氏。

        【讨论】:

        • 但是你可以很容易地返回一个new DictionaryEntry<string,string>(q.FirstName,q.Surname),它具有更强的打字优势,但是一个元组 更好。
        猜你喜欢
        • 2011-09-09
        • 2022-11-15
        • 1970-01-01
        • 1970-01-01
        • 2015-05-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-06-22
        相关资源
        最近更新 更多