【问题标题】:Get value from array if not out of bounds如果未超出范围,则从数组中获取值
【发布时间】:2022-04-05 04:17:17
【问题描述】:

我正在寻找最优雅的解决方案,以便在请求的索引未超出范围时从 object[] 获取值。

我目前的解决方案如下:

    public object GetNamedParametersFrom(GenericObject genericObject)
    {
        string nameFromListOne = String.Empty;
        string nameFromListTwo = String.Empty;

        for (int i = 0; i < genericObject.ListOfThings.Count; i++)
        {
            switch (i)
            {
                case 0:
                    nameFromListOne = genericObject.ListOfThings[i].Name;
                    break;
                case 1:
                    nameFromListTwo = genericObject.ListOfThings[i].Name;
                    break;
            }
        }

        return new {
           nameFromListOne,
           nameFromListTwo
        }
    }

【问题讨论】:

  • resourceSix之类的变量多吗?
  • 目前该项目只要求这两个 - 但是如果可能的话,我想满足这个要求。
  • 代码无法编译 - object 是保留关键字,如果 object.Resourcesobject[],则没有 Name 属性。不妨提供所需的演员表,也许它会影响什么是“最优雅的解决方案”

标签: c# arrays


【解决方案1】:

为什么不使用 Linq 内置的 ElementAtOrDefault 方法?

string[] names =
    { "Hartono, Tommy", "Adams, Terry", "Andersen, Henriette Thaulow",
        "Hedlund, Magnus", "Ito, Shu" };

int index = 20;

string name = names.ElementAtOrDefault(index);

【讨论】:

  • 这是最佳答案! ElementAtOrDefault 检查 IList 的可枚举以避免性能问题,正如 Rasmus 所说,它是内置的。
  • 最新最好的答案。
  • 标记为相关性的答案。
  • Z 是 Z 天才程序maa
【解决方案2】:

为什么不使用Array

public object GetNamedParametersFrom(GenericObject genericObject)
{
    string[] namesFromLists = new string[genericObject.ListOfThings.Count];

    for (int i = 0; i < genericObject.ListOfThings.Count; i++)
    {
        namesFromLists[i] = genericObject.ListOfThings[i].Name;
    }

    return namesFromLists; //As you are returning an `object`, you can return `resources` array directly from this method
}

【讨论】:

  • 这仍然会回到原来的问题——我需要将它们分配给原始类型属性,所以我只是从列表中创建一个数组来尝试追加(如果有的话)。
  • 您想展示一个示例或实际代码吗?实际上对我来说还不够清楚。
【解决方案3】:

扩展方法怎么样:

public static TValue GetSafe<TItem, TValue>(this IList<TItem> list, 
    int index, Func<TItem, TValue> selector, TValue defaultValue)
{
  // other checks omitted
  if (index < 0 || index >= list.Count)
  {
    return defaultValue;
  }
  return selector(list[index]);
}

你可以这样使用:

var items = new[] {"Hello", "World", "!"};

var value0 = items.GetSafe(0, s => s.Length, 0);
var value1 = items.GetSafe(1, s => s.Length, 0);
var value2 = items.GetSafe(2, s => s.Length, 0);
var value3 = items.GetSafe(3, s => s.Length, 0);

最后一行不会引发错误,value3 将设置为 0defaultValue)。

【讨论】:

    【解决方案4】:

    我知道这有一个公认的答案,但在我看来,一个更优雅、更简单的解决方案是这样的:

    var item = items.Length > n
                    ? resourceProperties[n]
                    : <default value you want to return if it's out of bounds>;
    

    items 是一个集合

    【讨论】:

      【解决方案5】:

      如果您只想获得一个resource,请输入请求的index

         if(index < object.Resources.Count){
               resource = object.Resources[index].Name;
          }
      

      【讨论】:

        【解决方案6】:

        使用扩展方法

        public T TryGetElement<T>(this T[] array, int index, T defaultElement) {
          if ( index < array.Length ) {
            return array[index];
          }
          return defaultElement;
        }
        

        这样使用

        // Select name to a string[]
        var names = @object.Resources.Select(i => i.Name).ToArray();
        
        resourceOne = names.TryGetElement(0, null);
        resourceTwo = names.TryGetElement(1, null);
        

        【讨论】:

        • 如果names只有1个呢?
        • @SemiDemented names 是一个数组,当然可以有0到n项
        • 我不认为你明白我的意思。如果您只有一项,names[1] 会抛出异常。
        【解决方案7】:

        Eric 的方法很好;但应该对数组进行完整的边界检查:

        public T ElementOrDefault<T>(this T[] array, int index, T defaultElement) {
          if ( index < array.GetLowerBound(0) || index > array.GetUpperBound(0) ) {
            return defaultElement;
          }
          return array[index];
        }
        

        【讨论】:

        • 我还可以补充一点,这样的方法是有充分理由的。在单元测试中,您可能想要检查预期数组是否与实际数组相同。这种方法无需太多安全检查代码就可以轻松完成。
        【解决方案8】:

        正如 Rasmus 所说,使用 LINQ 的 ElementAtOrDefault 是您最好的选择。如果您不能保证元素的数量,请添加一些 NULL 检查。

        string[] fruits = { "Apples", "Oranges", "Blueberries", "Pineapple" };
        
        string? thirdFruit = fruits?.ElementAtOrDefault(2); // Blueberries
        string? tenthFruit = fruits?.ElementAtOrDefault(9); // NULL
        string? negativeFruit = fruits?.ElementAtOrDefault(-1); // NULL
        

        【讨论】:

          猜你喜欢
          • 2012-08-24
          • 2018-10-16
          • 2021-06-26
          • 2017-07-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-07-18
          相关资源
          最近更新 更多