你是怎么做到的?给定一个字节数组:
byte[] foo = new byte[4096];
我如何得到数组的前x字节作为一个单独的数组?(具体来说,我需要它作为一个IEnumerable<byte>)
这是用于使用Sockets的。我认为最简单的方法是数组切片,类似于perl语法:
@bar = @foo[0..40];
将前41个元素返回到@bar数组中。c#中是否有我遗漏的东西,或者有其他我应该做的事情?
LINQ对我来说是一个选择。NET 3.5),如果有帮助的话。
你是怎么做到的?给定一个字节数组:
byte[] foo = new byte[4096];
我如何得到数组的前x字节作为一个单独的数组?(具体来说,我需要它作为一个IEnumerable<byte>)
这是用于使用Sockets的。我认为最简单的方法是数组切片,类似于perl语法:
@bar = @foo[0..40];
将前41个元素返回到@bar数组中。c#中是否有我遗漏的东西,或者有其他我应该做的事情?
LINQ对我来说是一个选择。NET 3.5),如果有帮助的话。
当前回答
您可以对原始数组(即IList)使用包装器,就像下面(未经测试的)代码一样。
public class SubList<T> : IList<T>
{
#region Fields
private readonly int startIndex;
private readonly int endIndex;
private readonly int count;
private readonly IList<T> source;
#endregion
public SubList(IList<T> source, int startIndex, int count)
{
this.source = source;
this.startIndex = startIndex;
this.count = count;
this.endIndex = this.startIndex + this.count - 1;
}
#region IList<T> Members
public int IndexOf(T item)
{
if (item != null)
{
for (int i = this.startIndex; i <= this.endIndex; i++)
{
if (item.Equals(this.source[i]))
return i;
}
}
else
{
for (int i = this.startIndex; i <= this.endIndex; i++)
{
if (this.source[i] == null)
return i;
}
}
return -1;
}
public void Insert(int index, T item)
{
throw new NotSupportedException();
}
public void RemoveAt(int index)
{
throw new NotSupportedException();
}
public T this[int index]
{
get
{
if (index >= 0 && index < this.count)
return this.source[index + this.startIndex];
else
throw new IndexOutOfRangeException("index");
}
set
{
if (index >= 0 && index < this.count)
this.source[index + this.startIndex] = value;
else
throw new IndexOutOfRangeException("index");
}
}
#endregion
#region ICollection<T> Members
public void Add(T item)
{
throw new NotSupportedException();
}
public void Clear()
{
throw new NotSupportedException();
}
public bool Contains(T item)
{
return this.IndexOf(item) >= 0;
}
public void CopyTo(T[] array, int arrayIndex)
{
for (int i=0; i<this.count; i++)
{
array[arrayIndex + i] = this.source[i + this.startIndex];
}
}
public int Count
{
get { return this.count; }
}
public bool IsReadOnly
{
get { return true; }
}
public bool Remove(T item)
{
throw new NotSupportedException();
}
#endregion
#region IEnumerable<T> Members
public IEnumerator<T> GetEnumerator()
{
for (int i = this.startIndex; i < this.endIndex; i++)
{
yield return this.source[i];
}
}
#endregion
#region IEnumerable Members
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
#endregion
}
其他回答
可以使用数组的CopyTo()方法。
或者使用LINQ,你可以使用Skip()和Take()…
byte[] arr = {1, 2, 3, 4, 5, 6, 7, 8};
var subset = arr.Skip(2).Take(2);
在c# 7.2中,您可以使用Span<T>。新制度的好处。内存系统的优点是它不需要到处复制数据。
你需要的方法是切片:
Span<byte> slice = foo.Slice(0, 40);
现在很多方法都支持Span和IReadOnlySpan,所以使用这个新类型非常简单。
请注意,在撰写本文时,Span<T>类型在。net的最新版本(4.7.1)中还没有定义,因此要使用它,您需要安装系统。来自NuGet的内存包。
我不认为c#支持范围语义。你也可以写一个扩展方法,比如:
public static IEnumerator<Byte> Range(this byte[] array, int start, int end);
但就像其他人说的,如果你不需要设置一个开始索引,那么Take就是你所需要的。
您可以使用Take扩展方法
var array = new byte[] {1, 2, 3, 4};
var firstTwoItems = array.Take(2);
对于字节数组,System.Buffer.BlockCopy会给你最好的性能。