C#中的数组用法详解

目录
  • 一.简单数组(一维数组)
    • 1.数组的声明
    • 2.数组的初始化
    • 3.访问数组元素
    • 4.数组中使用引用类型
  • 二.多维数组
  • 三.锯齿数组
  • 四.Array类
    • 1.创建数组
    • 2.复制数组
    • 3.排序
  • 五.数组作为参数
    • 1.数组协变
    • 2.ArraySegment<T>
  • 六.枚举集合
    • 1.IEnumerator接口
    • 2.foreach语句
    • 3.yield语句
      • (1).迭代集合的不同方式
      • (2).用yield return 返回枚举器
  • 七.元组(Tuple)
  • 八.结构比较

如果需要使用同一类型的多个对象,可以使用数组和集合(后面介绍)。C#用特殊的记号声明,初始化和使用数组。Array类在后台发挥作用,它为数组中的元素排序和过滤提供了多个方法。使用枚举器,可以迭代数组中的所有元素。
如果需要使用不同类型的多个对象,可以使用Tuple(元组)类型。

一.简单数组(一维数组)

数组是一种数据结构,它可以包含同一个类型的多个元素。

1.数组的声明

在声明数组时,先定义数组中的元素类型,其后是一对空方括号和一个变量名。

int[] myArray;

2.数组的初始化

声明了数组之后,就必须为数组分配内存,以保存数组的所有元素。数组是引用类型,所以必须给它分配堆上的内存。为此,应使用new运算符,指定数组中元素的类型和数量来初始化数组的变量。

myArray = new int[4];

在声明和初始化数组后,变量myArray就引用了4个整数值,它们位于托管堆上:

在指定了数组的大小后,就不能重新设置数组的大小。如果事先不知道数组中应包含多少个元素,就可以使用集合。
除了在两个语句中声明和初始化数组之外,还可以在一个语句中声明和初始化数组:

int[] myArray = new int[4];

还可以使用数组初始化器为数组的每个元素复制。数组初始化器只能在声明数组变量时使用,不能在声明数组之后使用。

int[] myArray = new int[4]{1,3,5,7};

如果用花括号初始化数组,可以不指定数组的大小,因为编译器会自动统计元素的个数:

int[] myArray = new int[]{1,3,5,7};

也可以使用更简单的形式:

int[] myArray = {1,3,5,7};

3.访问数组元素

在声明和初始化数组之后,就可以使用索引器访问其中的元素了。数组只支持有整型参数的索引器。
索引器总是以0开头,表示第一个元素。可以传递给索引器的最大值是元素个数减1,因为索引从0开始:

int[] myArray = {1,3,5,7};
int v1 = myArray[0];
int v2 = myArray[1];
myArray[3] = 4;

可以使用数组的Length属性获取元素的个数。

4.数组中使用引用类型

数组除了能声明预定义类型的数组,还可以声明自定义类型的数组。

  public class Person
  {
    public string FirstName { get; set; }

    public string LastName { get; set; }

    public override string ToString()
    {
      return String.Format("{0} {1}", FirstName, LastName);
    }
  }

  Person[] myPersons = new Person[2];
  myPersons[0] = new Person { FirstName = "Ayrton", LastName = "Senna" };
  myPersons[1] = new Person { FirstName = "Michael", LastName = "Schumacher" };

如果数组中的元素是引用类型,就必须为每个数组元素分配内存。如果使用了数组中未分配内存的元素,就会抛出NullReferenceException类型的异常。
下面是内存情况:

对自定义类型也可以使用数组初始化器:

  Person[] myPersons2 =
  {
    new Person { FirstName="Ayrton", LastName="Senna"},
    new Person { FirstName="Michael", LastName="Schumacher"}
  };

二.多维数组

多维数组用两个或多个整数来索引。
在C#中声明多维数组,需要在方括号中加上逗号。数组在初始化时应指定每一维的大小(也称为阶)。

int[,] twoDim = new int[3,3];
twoDim[0,0] = 1;
twoDim[0,1] = 2;
twoDim[0,2] = 3;
twoDim[1,0] = 4;
twoDim[1,1] = 5;
twoDim[1,2] = 6;
twoDim[2,0] = 7;
twoDim[2,1] = 8;
twoDim[2,2] = 9;

声明数组之后,就不能修改其阶数了。
也可以使用初始化器来初始化多维数组:

  int[,] twoDim ={
    {1,2,3},
    {4,5,6},
    {7,8,9}
    };

使用数组初始化器时,必须初始化数组的每个元素,不能遗漏任何元素。
声明一个三位数组:

  int[,,] threeDim ={
    {{1,2},{3,4}},
    {{5,6},{7,8}},
    {{9,10},{11,12}}
    };
  Console.WriteLine(threeDim[0,1,1]);

三.锯齿数组

二维数组的大小对应于一个矩形,而锯齿数组的大小设置比较灵活,在锯齿数组中,每一行都可以有不同的大小。
在声明锯齿数组时,要依次放置左右括号。在初始化锯齿数组时,只在第一对方括号中设置该数组包含的行数。定义各行中元素个数的第二个方括号设置为空,因为这类数组的每一行包含不同的元素个数。之后,为每一行指定行中的元素个数:

  int[][] jagged = new int[3][];
  jagged[0] = new int[2]{1,2};
  jagged[1] = new int[4]{3,4,5,6};
  jagged[2] = new int[3]{7,8};

迭代锯齿数组中的所有元素的代码可以放在嵌套的for循环中。在外层的for循环中迭代每一行,在内层的for循环中迭代一行中的每个元素:

  for(int row = 0;row<jagged.Length;row++)
  {
    for(int element = 0;element<jagged[row].Length;element++)
    {
      Console.WriteLine("row:{0}, element:{1},value:{2}",row,element,jagged[row][element]);
    }
  }

四.Array类

用方括号声明数组是C#中使用Array类的表示法。在后台使用C#语法,会创建一个派生自抽象基类Array的新类。这样,就可以使用Array类为每个C#数组定义的方法和属性了。
Array类实现的其它属性有LongLength和Rank。如果数组包含的元素个数超出了整数的取值范围,就可以使用LongLength属性来获得元素个数。使用Rank属性可以获得数组的维数。

1.创建数组

Array类是一个抽象类,所以不能使用构造函数来创建数组。但除了使用C#语法创建数组实例之外,还可以使用静态方法CreateInstance()创建数组。如果事先不知道元素的类型,该静态方法就很有用,因为类型可以作为Type对象传递给CreateInstance()方法。
CreateInstance()方法的第一个参数是元素的类型,第二个参数定义数组的大小。
可以使用SetValue()方法设置对应元素的值,用GetValue()方法读取对应元素的值。

  Array intArray1 = Array.CreateInstance(typeof(int), 5);
  for (int i = 0; i < 5; i++)
  {
    intArray1.SetValue(33, i);
  }

  for (int i = 0; i < 5; i++)
  {
    Console.WriteLine(intArray1.GetValue(i));
  }

还可以将已经创建的数组强制转换称声明为int[]的数组:

int[] intArray2 = (int[])intArray1;

CreateInstance()方法有许多重载版本,可以创建多维数组和索引不基于0的数组。

  //创建一个2X3的二维数组,第一维基于1,第二维基于10:
  int[] lengths = { 2, 3 };
  int[] lowerBounds = { 1, 10 };
  Array racers = Array.CreateInstance(typeof(Person), lengths, lowerBounds);

  racers.SetValue(new Person { FirstName = "Alain", LastName = "Prost" }, index1: 1, index2: 10);
  racers.SetValue(new Person
  {
    FirstName = "Emerson",
    LastName = "Fittipaldi"
  }, 1, 11);
  racers.SetValue(new Person { FirstName = "Ayrton", LastName = "Senna" }, 1, 12);
  racers.SetValue(new Person { FirstName = "Michael", LastName = "Schumacher" }, 2, 10);
  racers.SetValue(new Person { FirstName = "Fernando", LastName = "Alonso" }, 2, 11);
  racers.SetValue(new Person { FirstName = "Jenson", LastName = "Button" }, 2, 12);

  Person[,] racers2 = (Person[,])racers;
  Person first = racers2[1, 10];
  Person last = racers2[2, 12];

2.复制数组

因为数组是引用类型,所以将一个数组变量赋予另一个数组变量,就会得到两个引用同一数组的变量。
数组实现ICloneable接口。这个接口定义的Clone()方法会复制数组,创建数组的浅表副本。
如果数组的元素是值类型,Clone()方法会复制所有值:

  int[] a1 = {1,2};
  int[] a2 = (int[])a1.Clone();

如果数组包含引用类型,只复制引用。
除了使用Clone()方法之外,还可以使用Array.Copy()方法创建浅表副本。

  Person[] beatles = {
    new Person { FirstName="John", LastName="Lennon" },
    new Person { FirstName="Paul", LastName="McCartney" }
  };

  Person[] beatlesClone = (Person[])beatles.Clone();
  Person[] beatlesClone2 = new Person[2];
  Array.Copy(beatlesClone,beatlesClone2,2);//注意与Clone的语法区别,Copy需要传递阶数相同的已有数组。(还可以使用CopyTo()方法)

3.排序

Array类使用快速排序算法对数组中的元素进行排序。Sort()方法需要数组中的元素实现IComparable接口。因为简单类型(如String,Int32)实现IComparable接口,所以可以对包含这些类型的元素排序。

    string[] names = {
    "Christina Aguilera",
    "Shakira",
    "Beyonce",
    "Gwen Stefani"
    };

    Array.Sort(names);

    foreach (string name in names)
    {
      Console.WriteLine(name);
    }

如果对数组使用使用自定义类,就必须实现IComparable接口。这个接口只定义了一个方法CompareTo()方法,如果要比较的对象相等,该方法就返回0.如果该实例应排在参数对象的前面,该方法就返回小于i0de值。如果该实例应排在参数对象的后面,该方法就返回大于0的值。

  public class Person : IComparable<Person>
  {
    public string FirstName { get; set; }

    public string LastName { get; set; }

    public override string ToString()
    {
      return String.Format("{0} {1}",
      FirstName, LastName);
    }

    public int CompareTo(Person other)
    {
      if (other == null) throw new ArgumentNullException("other");

      int result = this.LastName.CompareTo(other.LastName);
      if (result == 0)
      {
        result = this.FirstName.CompareTo(other.FirstName);
      }

      return result;
    }
  }

客户端代码:

  Person[] persons = {
  new Person { FirstName="Damon", LastName="Hill" },
  new Person { FirstName="Niki", LastName="Lauda" },
  new Person { FirstName="Ayrton", LastName="Senna" },
  new Person { FirstName="Graham", LastName="Hill" }
  };
  Array.Sort(persons);
  foreach (Person p in persons)
  {
    Console.WriteLine(p);
  }

如果Person对象的排序方式与上述不同,或者不能修改在数组中用作元素的类,就可以实现IComparer接口或IComparer<T>接口。这两个接口定义了方法Compare()方法。机型比较的类必须实现这两个接口之一。

  public enum PersonCompareType
  {
    FirstName,
    LastName
  }
  //通过使用实现了IComparer<T> 泛型接口的PersonComparer类比较Person对象数组。
  public class PersonComparer : IComparer<Person>
  {
    private PersonCompareType compareType;

    public PersonComparer(PersonCompareType compareType)
    {
      this.compareType = compareType;
    }

    #region IComparer<Person> Members

    public int Compare(Person x, Person y)
    {
        if (x == null) throw new ArgumentNullException("x");
        if (y == null) throw new ArgumentNullException("y");

      switch (compareType)
      {
        case PersonCompareType.FirstName:
          return x.FirstName.CompareTo(y.FirstName);
        case PersonCompareType.LastName:
          return x.LastName.CompareTo(y.LastName);
        default:
          throw new ArgumentException(
          "unexpected compare type");
      }
    }

    #endregion
  }

客户端代码:

  Person[] persons = {
  new Person { FirstName="Damon", LastName="Hill" },
  new Person { FirstName="Niki", LastName="Lauda" },
  new Person { FirstName="Ayrton", LastName="Senna" },
  new Person { FirstName="Graham", LastName="Hill" }
  };
  Array.Sort(persons,
  new PersonComparer(PersonCompareType.FirstName));

  foreach (Person p in persons)
  {
    Console.WriteLine(p);
  }

五.数组作为参数

数组可以作为参数传递给方法,也可以从方法中返回。

1.数组协变

数组支持协变。这表示数组可以声明为基类,其派生类型的元素可以赋值于数组元素。

  static void DisPlay(object[] o)
  {
    //..
  }

可以给该方法传递一个Person[]。
数组协变只能用于引用类型,不能用于值类型。

2.ArraySegment<T>

结构ArraySegment<T>表示数组的一段。如果需要使用不同的方法处理某个大型数组的不同部分,那么可以把相应的数组部分复制到各个方法。
ArraySegment<T>结构包含了关于数组段的信息(偏移量和元素个数)。

  static void Main()
  {
    int[] ar1 = { 1, 4, 5, 11, 13, 18 };
    int[] ar2 = { 3, 4, 5, 18, 21, 27, 33 };
    var segments = new ArraySegment<int>[2]
    {
      new ArraySegment<int>(ar1, 0, 3),
      new ArraySegment<int>(ar2, 3, 3)
    };

    var sum = SumOfSegments(segments);
    Console.WriteLine("sum of all segments: {0}", sum);

  }

  static int SumOfSegments(ArraySegment<int>[] segments)
  {
  int sum = 0;
  foreach (var segment in segments)
  {
    for (int i = segment.Offset; i < segment.Offset + segment.Count; i++)
    {
        sum += segment.Array[i];
    }

  }
  return sum;
  }

数组段不复制原数组的元素,但原数组可以通过ArraySegment<T>访问。如果数组段中的元素改变了,这些变化就会反映到原数组中。

六.枚举集合

在foreach语句中使用枚举,可以迭代集合中的元素,且无需知道集合中元素的个数。foreach语句使用一个枚举器。foreach会调用实现了IEnumerable接口的集合类中的GetEumerator()方法。GetEumerator()方法返回一个实现IEnumerator接口的对象枚举。foreach语句就可以使用IEnumerable接口迭代集合了。
GetEumerator()方法在IEnumerable接口中定义。

1.IEnumerator接口

foreach语句使用IEnumerator接口的方法和属性,迭代集合中所有元素。IEnumerator接口定义了Current属性,来返回光标所在的元素,该接口的MoveNext()方法移动到集合的下一个元素上,如果有这个元素,该方法就返回true。如果集合不再有更多的元素,该方法就返回false.
这个接口的泛型版本IEnumerator<T>派生自接口IDisposable,因此定义了Dispose()方法,来清理枚举器占用的资源。

2.foreach语句

C#中foreach语句不会解析为IL代码中的foreach语句。C#编译器会把foreach语句转换为IEnumerator接口的方法和属性。

  Person[] persons = {
    new Person { FirstName="Damon", LastName="Hill" },
    new Person { FirstName="Niki", LastName="Lauda" },
    new Person { FirstName="Ayrton", LastName="Senna" },
    new Person { FirstName="Graham", LastName="Hill" }
  };
  foreach (Person p in persons)
  {
    Console.WriteLine(p);
  }

foreach语句会解析为下面的代码:

  IEnumerator<Person> enumerator = persons.GetEumerator();
  while(enumerator.MoveNext())
  {
    Person p = enumerator.Current;
    Console.WriteLine(p);
  }

3.yield语句

在C#2.0之前,foreach语句可以轻松的迭代集合,但创建枚举器需要做大量的工作。C#2.0添加了yield语句,以便创建枚举器。
yield return 语句返回集合的一个元素,并移动到下一个元素。yield break可停止迭代。
下面的例子实现返回两个字符串:

  public class HelloCollection
  {
    public IEnumerator<string> GetEnumerator()
    {
    yield return "Hello";
    yield return "World";
    }
  }

客户端代码:

  var helloCollection = new HelloCollection();
  foreach (string s in helloCollection)
  {
    Console.WriteLine(s);
  }

包含yield语句的方法或属性也称为迭代块。迭代块必须声明为返回IEnumerator或IEnumerable接口,或者这些接口的泛型版本。这个块可以包含多条yield return语句或yield break语句,但不能包含return语句。
使用迭代块,编译器会生成一个yield类型,其中包含一个状态机,如下面代码所示:
yield类型实现IEnumerator和IDisposable接口的方法和属性。下面的例子可以把yield类型看作内部类Enumerator。外部类的GetEnumerator()方法实例化并返回一个新的yield类型。在yield类型中,变量state定义了迭代的当前位置,每次调用MoveNext()时,当前位置都会改变。MoveNext()封装了迭代块的代码,并设置了current变量的值,从而使Current属性根据位置返回一个对象。

  public class HelloCollection
  {
    public IEnumerator<string> GetEnumerator()
    {
      return new Enumerator(0);
    }

  public class Enumerator:IEnumerator<string>,IEnumerator,IDisposable
  {
    private int state;
    private string current;

    public Enumerator(int state)
    {
      this.state = state;
    }

    bool System.Collections.IEnumerator.MoveNext()
    {
      switch(state)
      {
        case 0:
          current="hello";
          state =1;
          return true;
        case 1:
          current="world";
          state =2;
          return true;
        case 2:
          break;
      }

      return false;
    }

    void System.Collection>IEnumerator.Reset()
    {
      throw new NotSupportedException();
    }

    string System.Collections.Generic.IEnumerator<string>.Current
    {
      get
      {
        return current;
      }
    }

    object System.Collections.IEnumerator.Current
    {
      get
      {
        return current;
      }
    }

    void IDisposable.Dispose()
    {}
  }
}

yield语句会产生一个枚举器,而不仅仅生成一个包含的项的列表。这个枚举器通过foreach语句调用。从foreach中依次访问每一项,就会访问枚举器。这样就可以迭代大量的数据,而无需一次把所有的数据都读入内存。

(1).迭代集合的不同方式

可以使用yield return语句,以不同方式迭代集合。
类MusicTitles可以用默认方式通过GetEnumerator()方法迭代标题,该方法不必在代码中编写,也可以用Reverse()逆序迭代标题,用Subset()方法迭代子集合:

    public class MusicTitles
    {
      string[] names = {
      "Tubular Bells", "Hergest Ridge",
      "Ommadawn", "Platinum" };

      public IEnumerator<string> GetEnumerator()
      {
        for (int i = 0; i < 4; i++)
        {
          yield return names[i];
        }
      }

      public IEnumerable<string> Reverse()
      {
        for (int i = 3; i >= 0; i--)
        {
          yield return names[i];
        }
      }

      public IEnumerable<string> Subset(int index, int length)
      {
        for (int i = index; i < index + length;i++)
        {
          yield return names[i];
        }
      }
    }

客户端代码:

    var titles = new MusicTitles();
    foreach (var title in titles)
    {
      Console.WriteLine(title);
    }
    Console.WriteLine();

    Console.WriteLine("reverse");
    foreach (var title in titles.Reverse())
    {
      Console.WriteLine(title);
    }
    Console.WriteLine();

    Console.WriteLine("subset");
    foreach (var title in titles.Subset(2, 2))
    {
      Console.WriteLine(title);
    }

(2).用yield return 返回枚举器

public class GameMoves
  {
    private IEnumerator cross;
    private IEnumerator circle;

    public GameMoves()
    {
      cross = Cross();
      circle = Circle();
    }

    private int move = 0;
    const int MaxMoves = 9;

    public IEnumerator Cross()
    {
      while (true)
      {
        Console.WriteLine("Cross, move {0}", move);
        if (++move >= MaxMoves)
          yield break;
        yield return circle;
      }
    }

    public IEnumerator Circle()
    {
      while (true)
      {
        Console.WriteLine("Circle, move {0}", move);
        if (++move >= MaxMoves)
          yield break;
        yield return cross;
      }
    }
  }

客户端代码:

    var game = new GameMoves();

    IEnumerator enumerator = game.Cross();
    while (enumerator.MoveNext())
    {
      enumerator = enumerator.Current as IEnumerator;
    }

这样会交替调用Cross()和Circle()方法。

七.元组(Tuple)

元组可以合并不同类型的对象。元组起源于函数编程语言,如F#。在.NET Framework中,元组可用于所有的.Net语言。
.NET Framework定义了8个泛型Tuple类和一个静态Tuple类,它们用作元组的工厂。不同的泛型Tuple类支持不同数量的元素。如,Tuple<T1>包含一个元素,Tuple<T1,T2>包含两个元素。

Tuple<string, string> name = new Tuple<string, string>("Jochen", "Rindt");

元组也可以用静态Tuple类的静态Create()方法创建。Create()方法的泛型参数定了要实例化的元组类型:

  public static Tuple<int, int> Divide(int dividend, int divisor)
  {
    int result = dividend / divisor;
    int reminder = dividend % divisor;

    return Tuple.Create<int, int>(result, reminder);
  }

可以用属性Item1和Item2访问元组的项:

  var result = Divide(5, 2);
  Console.WriteLine("result of division: {0}, reminder: {1}", result.Item1, result.Item2);

如果元组包含的项超过8个,就可以使用带8个参数的Tuple类定义。最后一个模板参数是TRest,表示必须给它传递一个元组。这样,就可以创建带任意个参数的元组了。

  var tuple = Tuple.Create<string, string, string, int, int, int, double, Tuple<int, int>>(
  "Stephanie", "Alina", "Nagel", 2009, 6, 2, 1.37, Tuple.Create<int, int>(52, 3490));

八.结构比较

数组和元组都实现接口IStructuralEquatable和IStructuralComparable。这两个接口不仅可以比较引用,还可以比较内容。这些接口都是显式实现的,所以在使用时需要把数组和元组强制转换为这个接口。
IStructuralEquatable接口用于比较两个元组或数组是否有相同的内同,IStructuralComparable接口用于给元组或数组排序。
IStructuralEquatable接口示例:
编写实现IEquatable接口的Person类,IEquatable接口定义了一个强类型化的Equals()方法,比较FirstName和LastName的值:

public class Person : IEquatable<Person>
  {
    public int Id { get; private set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }

    public override string ToString()
    {
      return String.Format("{0}, {1} {2}", Id, FirstName, LastName);
    }

    public override bool Equals(object obj)
    {
        if (obj == null)
            return base.Equals(obj);
        return Equals(obj as Person);
    }

    public override int GetHashCode()
    {
        return Id.GetHashCode();
    }

    #region IEquatable<Person> Members

    public bool Equals(Person other)
    {
      if (other == null)
        return base.Equals(other);

      return this.FirstName == other.FirstName && this.LastName == other.LastName;
    }

    #endregion
  }

创建两个包含相同内容的Person类型的数组:

  var janet = new Person { FirstName = "Janet", LastName = "Jackson" };
  Person[] persons1 = { new Person { FirstName = "Michael", LastName = "Jackson" }, janet };
  Person[] persons2 = { new Person { FirstName = "Michael", LastName = "Jackson" }, janet };

由于两个变量引用两个不同数组,所以!=返回True:

  if (persons1 != persons2)
    Console.WriteLine("not the same reference");

对于IStructuralEquatable接口定义的Equals方法,第一个参数是object类型,第二个参数是IEqualityComparer类型。调用这个方法时,通过传递一个实现了EqualityComparer<T>的对象,就可以定义如何进行比较。通过EqualityComparer<T>类完成IEqualityComparer的一个默认实现。这个实现检查T类型是否实现了IEquatable接口,并调用IEquatable.Equals()方法。如果该类没有实现IEquatable接口,就调用Object基类中Equals()方法:

  if ((persons1 as IStructuralEquatable).Equals(persons2, EqualityComparer<Person>.Default))
  {
    Console.WriteLine("the same content");
  }

元组示例:
Tuple<>类提供了两个Epuals()方法:一个重写了Object基类中的Epuals方法,并把object作为参数,第二个由IStructuralEquatable接口定义,并把object和IEqualityComparer作为参数。

  var t1 = Tuple.Create<int, string>(1, "Stephanie");
  var t2 = Tuple.Create<int, string>(1, "Stephanie");
  if (t1 != t2)
  Console.WriteLine("not the same reference to the tuple");

这个方法使用EqualityComparer<object>.Default获取一个ObjectEqualityComparer<object>,以进行比较。这样就会调用Object.Equals()方法比较元组的每一项:

  if (t1.Equals(t2))
    Console.WriteLine("equals returns true");

还可以使用TupleComparer类创建一个自定义的IEqualityComparer

  TupleComparer tc = new TupleComparer();

  if ((t1 as IStructuralEquatable).Equals(t2, tc))
  {
    Console.WriteLine("yes, using TubpleComparer");
  }

  class TupleComparer : IEqualityComparer
  {
    #region IEqualityComparer Members

    public new bool Equals(object x, object y)
    {
      bool result = x.Equals(y);
      return result;
    }

    public int GetHashCode(object obj)
    {
      return obj.GetHashCode();
    }

    #endregion
  }

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • C#中多维数组[,]和交错数组[][]的区别

    多维数组的声明 在声明时,必须指定数组的长度,格式为 type [lenght ,lenght ,lengh, ... ] int [,] test1 = new int [3,3]; 或声明时即赋值,由系统推断长度 int [,] test1 = { {1,2,3}, {1,2,3}, {1,2,3}, }; 交错数组的声明 声明时,至少需要指定第一维的长度,格式为 type [ ] [ ] [ ] ... int [][] test1 = new int[5][]; int [][] tes

  • 详解c# 数组(Array)

    数组是一个存储相同类型元素的固定大小的顺序集合.数组是用来存储数据的集合,通常认为数组是一个同一类型变量的集合. 声明数组变量并不是声明 number0.number1.....number99 一个个单独的变量,而是声明一个就像 numbers 这样的变量,然后使用 numbers[0].numbers[1].....numbers[99] 来表示一个个单独的变量.数组中某个指定的元素是通过索引来访问的. 所有的数组都是由连续的内存位置组成的.最低的地址对应第一个元素,最高的地址对应最后一个元

  • C# 数组中的 indexOf 方法及使用

    具体代码如下所示: var array=['REG','2018','2018']; array.indexOf('REG') // 0 array.indexOf('R') // -1 array.indexOf('2018′) // 1 array.indexOf(2018) // -1 arr.indexOf('orange') 输出 0 因为 'orange' 是数组的第 0 个元素,匹配到并返回下标. arr.indexOf('o') 输出 -1 因为此方法不会在每一个元素的基础上再次

  • 浅谈C#数组(一)

    目录 一.简单数组之一维数组 1.数组的声明 2.数组的初始化 3.访问数组元素 4.数组中使用引用类型 二.多维数组 三.锯齿数组 四.Array类 1.创建数组 2.复制数组 3.排序 五.数组作为参数 1.数组协变 2.ArraySegment<T> 前言: 如果需要使用同一类型的多个对象,可以使用数组和集合.C#用特殊的记号声明,初始化和使用数组.Array类在后台发挥作用,它为数组中的元素排序和过滤提供了多个方法.使用枚举器,可以迭代数组中的所有元素. 如果需要使用不同类型的多个对象

  • C# 删除数组内的某个值、一组值方法详解

    最近优化了一个权限校验的功能,之前每次其他系统在获取各自系统的权限配置时,sso都去找到本地对应的权限文件读取解析一次. 这种设计虽然可以实现功能,但是这种反复去读取的策略并不经济,尤其在高并发的情况下更可能会成为性能瓶颈. 于是我对这块业务进行了优化,而在优化的过程中针对如何去除数组内的某些参数试验了一些写法,下面记录我认为比较优雅的写法. 首先讲下场景,设计多系统的权限统一由sso控制,那么每次用户登录其他系统后需要向sso请求"用户在该系统已有的权限"或"该用户当前是否

  • 浅谈C#数组(二)

    目录 一.枚举集合 1.IEnumerator接口 2.foreach语句 3.yield语句 二.元组(Tuple) 三.结构比较 可以先了解上一篇文章内容C#数组(一) 一.枚举集合 在foreach语句中使用枚举,可以迭代集合中的元素,且无需知道集合中元素的个数.foreach语句使用一个枚举器.foreach会调用实现了IEnumerable接口的集合类中的GetEumerator()方法.GetEumerator()方法返回一个实现IEnumerator接口的对象枚举.foreach语

  • C#对多个集合和数组的操作方法(合并,去重,判断)

    在开发过程中.数组和集合的处理是最让我们担心.一般会用for or foreach 来处理一些操作.这里介绍一些常用的集合跟数组的操作函数. 首先举例2个集合A,B. List<int> listA = new List<int> {1,2,3,5,7,9}; List<int> listB = new List<int> {13,4,17,29,2}; listA.AddRange(listB ); 把集合A.B合并 List<int> Res

  • C# 字符串、数组和List的截取和转换实例

    如下所示: using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; using System.Threading; namespace ConsoleApp1 { class Program { /// <summary> /// 字符串,数组和List的截取,转换 /// </summary> /// <pa

  • C#实现char字符数组与字符串相互转换的方法

    本文实例讲述了C#实现char字符数组与字符串相互转换的方法.分享给大家供大家参考,具体如下: 一.字符串转换为字符数组 char[] tempChar = sourceString.ToCharArray(); 二.字符数组转换为字符串 //方法一 string str = string.Join("", tempChar); //方法二 string str = string.Concat<char>(tempChar); //方法三 string str = new

  • C#中的数组用法详解

    目录 一.简单数组(一维数组) 1.数组的声明 2.数组的初始化 3.访问数组元素 4.数组中使用引用类型 二.多维数组 三.锯齿数组 四.Array类 1.创建数组 2.复制数组 3.排序 五.数组作为参数 1.数组协变 2.ArraySegment<T> 六.枚举集合 1.IEnumerator接口 2.foreach语句 3.yield语句 (1).迭代集合的不同方式 (2).用yield return 返回枚举器 七.元组(Tuple) 八.结构比较 如果需要使用同一类型的多个对象,可

  • Angular 中 select指令用法详解

    最近在angular中使用select指令时,出现了很多问题,搞得很郁闷.查看了很多资料后,发现select指令并不简单,决定总结一下. select用法: <select ng-model="" [name=""] [required=""] [ng-required=""] [ng-options=""]> </select> 属性说明: 发现并没有ng-change属性 ng-

  • 浅谈c++中的stl中的map用法详解

    Map是STL的一个关联容器,它提供一对一(其中第一个可以称为关键字,每个关键字只能在map中出现一次,第二个可能称为该关键字的值)的数据处理能力,由于这个特性,它完成有可能在我们处理一对一数据的时候,在编程上提供快速通道.这里说下map内部数据的组织,map内部自建一颗红黑树(一种非严格意义上的平衡二叉树),这颗树具有对数据自动排序的功能,所以在map内部所有的数据都是有序的,后边我们会见识到有序的好处. 下面举例说明什么是一对一的数据映射.比如一个班级中,每个学生的学号跟他的姓名就存在着一一

  • Python中re.findall()用法详解

    在python中,通过内嵌集成re模块,程序媛们可以直接调用来实现正则匹配.本文重点给大家介绍python中正则表达式 re.findall 用法 re.findall():函数返回包含所有匹配项的列表.返回string中所有与pattern相匹配的全部字串,返回形式为数组. 示例代码1:[打印所有的匹配项] import re s = "Long live the people's Republic of China" ret = re.findall('h', s) print(r

  • 基于C++中setiosflags()的用法详解

    cout<<setiosflags(ios::fixed)<<setiosflags(ios::right)<<setprecision(2); setiosflags 是包含在命名空间iomanip 中的C++ 操作符,该操作符的作用是执行由有参数指定区域内的动作:   iso::fixed 是操作符setiosflags 的参数之一,该参数指定的动作是以带小数点的形式表示浮点数,并且在允许的精度范围内尽可能的把数字移向小数点右侧:   iso::right 也是se

  • java 中 ChannelHandler的用法详解

    java 中 ChannelHandler的用法详解 前言: ChannelHandler处理一个I/O event或者拦截一个I/O操作,在它的ChannelPipeline中将其递交给相邻的下一个handler. 通过继承ChannelHandlerAdapter来代替 因为这个接口有许多的方法需要实现,你或许希望通过继承ChannelHandlerAdapter来代替. context对象 一个ChannelHandler和一个ChannelHandlerContext对象一起被提供.一个

  • Java中isAssignableFrom的用法详解

    class1.isAssignableFrom(class2) 判定此 Class 对象所表示的类或接口与指定的 Class 参数所表示的类或接口是否相同,或是否是其超类或超接口.如果是则返回 true:否则返回 false.如果该 Class 表示一个基本类型,且指定的 Class 参数正是该 Class 对象,则该方法返回 true:否则返回 false. 1. class2是不是class1的子类或者子接口 2. Object是所有类的父类 一个例子搞定: package com.auuz

  • javascript中Array()数组函数详解

    在程序语言中数组的重要性不言而喻,JavaScript中数组也是最常使用的对象之一,数组是值的有序集合,由于弱类型的原因,JavaScript中数组十分灵活.强大,不像是Java等强类型高级语言数组只能存放同一类型或其子类型元素,JavaScript在同一个数组中可以存放多种类型的元素,而且是长度也是可以动态调整的,可以随着数据增加或减少自动对数组长度做更改. Array()是一个用来构建数组的内建构造器函数.数组主要由如下三种创建方式: array = new Array() array =

  • php 中的closure用法详解

    Closure,匿名函数,是php5.3的时候引入的,又称为Anonymous functions.字面意思也就是没有定义名字的函数.比如以下代码(文件名是do.php) <?php function A() { return 100; }; function B(Closure $callback) { return $callback(); } $a = B(A()); print_r($a);//输出:Fatal error: Uncaught TypeError: Argument 1

  • JavaScript中eval()函数用法详解

    eval() 函数计算 JavaScript 字符串,并把它作为脚本代码来执行. 如果参数是一个表达式,eval() 函数将执行表达式.如果参数是Javascript语句,eval()将执行 Javascript 语句. 语法 复制代码 代码如下: eval(string) 参数 描述 string 必需.要计算的字符串,其中含有要计算的 JavaScript 表达式或要执行的语句. eval()函数用法详解: 此函数可能使用的频率并不是太高,但是在某些情况下具有很大的作用,下面就介绍一下eva

随机推荐