Вы можете написать свой собственный класс ломтика достаточно легко:
public class ReadOnlyListSlice<T> : IReadOnlyList<T>
{
private readonly IReadOnlyList<T> _list;
private readonly int _start;
private readonly int _exclusiveEnd;
public ReadOnlyListSlice(IReadOnlyList<T> list, int start, int exclusiveEnd)
{
_list = list;
_start = start;
_exclusiveEnd = exclusiveEnd;
}
public IEnumerator<T> GetEnumerator()
{
for (int i = _start; i <= _exclusiveEnd; ++i)
yield return _list[i];
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public int Count
{
get { return _exclusiveEnd - _start; }
}
public T this[int index]
{
get { return _list[index+_start]; }
}
}
Использование:
List<int> ints = Enumerable.Range(1, 10).ToList();
var test = new ReadOnlyListSlice<int>(ints, 4, 7);
foreach (var i in test)
Console.WriteLine(i); // 5, 6, 7, 8
Console.WriteLine();
for (int i = 1; i < 3; ++i)
Console.WriteLine(test[i]); // 6, 7
Вы также можете написать записываемый версию, но если вы сделаете это осуществить IList<T>
вас В конце концов вам придется внедрить множество методов, которые вам, вероятно, не понадобится использовать.
Однако, если вы не возражаете, это только осуществление IReadOnlyList<T>
(и косвенно IEnumerable<T>
) это не так уж трудно:
public class ListSlice<T> : IReadOnlyList<T>
{
private readonly List<T> _list;
private readonly int _start;
private readonly int _exclusiveEnd;
public ListSlice(List<T> list, int start, int exclusiveEnd)
{
_list = list;
_start = start;
_exclusiveEnd = exclusiveEnd;
}
public IEnumerator<T> GetEnumerator()
{
for (int i = _start; i <= _exclusiveEnd; ++i)
yield return _list[i];
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public int Count
{
get { return _exclusiveEnd - _start; }
}
public T this[int index]
{
get { return _list[index+_start]; }
set { _list[index+_start] = value; }
}
}
И использовать:
List<int> ints = Enumerable.Range(1, 10).ToList();
var test = new ListSlice<int>(ints, 4, 7);
foreach (var i in test)
Console.WriteLine(i); // 5, 6, 7, 8
Console.WriteLine();
test[2] = -1;
for (int i = 1; i < 4; ++i)
Console.WriteLine(test[i]); // 6, -1, 8
Конечно, недостаток из невыполнения IList<T>
заключается в том, что вы не сможете передать ListSlice<T>
методу, ожидающему IList<T>
.
Я оставляю полную реализацию public class ListSlice<T> : IList<T>
пресловутому «Заинтересованному читателю».
Если вы хотите реализовать эквивалент List<T>.FIndIndex()
это тоже довольно просто.Просто добавьте в любой класс:
public int FindIndex(int startIndex, int count, Predicate<T> match)
{
for (int i = startIndex; i < startIndex + count; ++i)
if (match(this[i]))
return i;
return -1;
}
Вот полное компилируются консольное приложение:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
namespace Demo
{
public class ReadOnlyListSlice<T> : IReadOnlyList<T>
{
private readonly IReadOnlyList<T> _list;
private readonly int _start;
private readonly int _exclusiveEnd;
public ReadOnlyListSlice(IReadOnlyList<T> list, int start, int exclusiveEnd)
{
_list = list;
_start = start;
_exclusiveEnd = exclusiveEnd;
}
public IEnumerator<T> GetEnumerator()
{
for (int i = _start; i <= _exclusiveEnd; ++i)
yield return _list[i];
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public int Count
{
get { return _exclusiveEnd - _start; }
}
public T this[int index]
{
get { return _list[index + _start]; }
}
}
public class ListSlice<T> : IReadOnlyList<T>
{
private readonly IList<T> _list;
private readonly int _start;
private readonly int _exclusiveEnd;
public ListSlice(IList<T> list, int start, int exclusiveEnd)
{
_list = list;
_start = start;
_exclusiveEnd = exclusiveEnd;
}
public IEnumerator<T> GetEnumerator()
{
for (int i = _start; i <= _exclusiveEnd; ++i)
yield return _list[i];
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public int Count
{
get { return _exclusiveEnd - _start; }
}
public T this[int index]
{
get { return _list[index+_start]; }
set { _list[index+_start] = value; }
}
}
internal class Program
{
private static void Main()
{
var ints = Enumerable.Range(1, 10).ToList();
Console.WriteLine("Readonly Demo\n");
demoReadOnlySlice(ints);
Console.WriteLine("\nWriteable Demo\n");
demoWriteableSlice(ints);
}
private static void demoReadOnlySlice(List<int> ints)
{
var test = new ReadOnlyListSlice<int>(ints, 4, 7);
foreach (var i in test)
Console.WriteLine(i); // 5, 6, 7, 8
Console.WriteLine();
for (int i = 1; i < 4; ++i)
Console.WriteLine(test[i]); // 6, 7, 8
}
private static void demoWriteableSlice(List<int> ints)
{
var test = new ListSlice<int>(ints, 4, 7);
foreach (var i in test)
Console.WriteLine(i); // 5, 6, 7, 8
Console.WriteLine();
test[2] = -1;
for (int i = 1; i < 4; ++i)
Console.WriteLine(test[i]); // 6, -1, 8
}
}
}
_ «если возможно по ссылке». _ Вы хотите, чтобы, если вы обновляете общий элемент в одном списке, он также обновляется в другом списке? –
http://stackoverflow.com/questions/1396048/c-sharp-elegant-way-of-partitioning-a-list –
В зависимости от того, что вы хотите, вы можете создать класс, содержащий ссылку на список и два целых числа. Пожалуйста, объясните свой прецедент лучше и почему вы думаете, что «по ссылке» поможет. – CodeCaster