목록을 초기화하는 방법 (용량이 아닌) 주어진 크기로?
.NET은 성능이 거의 동일한 일반 목록 컨테이너를 제공합니다 (배열 대 목록의 성능 질문 참조). 그러나 초기 화면에서 상당히 다릅니다.
배열은 기본값으로 초기화하기가 매우 쉽고 정의에 따라 이미 특정 크기가 있습니다.
string[] Ar = new string[10];
임의의 항목을 안전하게 할당 할 수 있습니다.
Ar[5]="hello";
목록을 사용하면 더 까다 롭습니다. 동일한 초기화를 수행하는 두 가지 방법을 볼 수 있습니다. 둘 다 우아하다고 부르는 것이 아닙니다.
List<string> L = new List<string>(10);
for (int i=0;i<10;i++) L.Add(null);
또는
string[] Ar = new string[10];
List<string> L = new List<string>(Ar);
더 깨끗한 방법은 무엇입니까?
편집 : 지금까지 답변은 목록을 미리 채우는 것보다 다른 용량을 나타냅니다. 예를 들어, 10 명의 용량으로 방금 생성 된 목록에서L[2]="somevalue"
편집 2 : 사람들은 내가 목록을 사용하려는 방식이 아니기 때문에 왜 이런 식으로 목록을 사용하고 싶은지 궁금합니다. 두 가지 이유를 알 수 있습니다.
목록이 "차세대"배열이라고 설득력있게 주장 할 수 있으므로 거의 패널티없이 유연성을 추가 할 수 있습니다. 따라서 기본적으로 사용해야합니다. 초기화하기가 쉽지 않을 수 있음을 지적하고 있습니다.
내가 현재 쓰고있는 것은 더 큰 프레임 워크의 일부로 기본 기능을 제공하는 기본 클래스입니다. 내가 제공하는 기본 기능에서 목록의 크기는 고급으로 알려져 있으므로 배열을 사용할 수 있습니다. 그러나 모든 기본 클래스에 동적으로 확장 할 수있는 기회를 제공하고 싶으므로 목록을 선택합니다.
나는 이것이 자주 필요하다고 말할 수 없습니다. 왜 이것을 원하는지에 대해 더 자세히 설명해 주시겠습니까? 아마도 도우미 클래스의 정적 메서드로 넣을 것입니다.
public static class Lists
{
public static List<T> RepeatedDefault<T>(int count)
{
return Repeated(default(T), count);
}
public static List<T> Repeated<T>(T value, int count)
{
List<T> ret = new List<T>(count);
ret.AddRange(Enumerable.Repeat(value, count));
return ret;
}
}
당신은 할 수 사용 Enumerable.Repeat(default(T), count).ToList()
하지만 크기 조정 버퍼하는 비효율적으로 인한 것입니다.
경우 참고 T
참조 형식은, 그것은 저장합니다 count
에 대한 통과 기준의 사본 value
그들은 모두 같은 객체를 참조 할 수 있도록 - 매개 변수를. 사용 사례에 따라 원하는 것일 수도 있고 아닐 수도 있습니다.
편집 : 주석에서 언급했듯이 Repeated
원하는 경우 루프를 사용하여 목록을 채울 수 있습니다. 그것도 약간 더 빠를 것입니다. 개인적으로 Repeat
더 설명적인 코드를 사용 하고 있으며 실제 환경에서는 성능 차이가 무관하다고 생각하지만 마일리지는 다를 수 있습니다.
List<string> L = new List<string> ( new string[10] );
int ( "capacity")를 인수로 사용하는 생성자를 사용하십시오.
List<string> = new List<string>(10);
편집 : 나는 Frederik에 동의한다는 것을 추가해야합니다. 당신은 처음에 그것을 사용하는 전체적인 추론에 반하는 방식으로 목록을 사용하고 있습니다.
EDIT2 :
편집 2 : 현재 작성중인 것은 더 큰 프레임 워크의 일부로 기본 기능을 제공하는 기본 클래스입니다. 내가 제공하는 기본 기능에서 목록의 크기는 고급으로 알려져 있으므로 배열을 사용할 수 있습니다. 그러나 모든 기본 클래스에 동적으로 확장 할 수있는 기회를 제공하고 싶으므로 목록을 선택합니다.
모든 null 값이있는 List의 크기를 알아야하는 이유는 무엇입니까? 목록에 실제 값이 없으면 길이가 0이 될 것으로 예상합니다. 어쨌든 이것이 어색하다는 사실은 그것이 의도 된 클래스 사용에 위배된다는 것을 보여줍니다.
Why are you using a List if you want to initialize it with a fixed value ? I can understand that -for the sake of performance- you want to give it an initial capacity, but isn't one of the advantages of a list over a regular array that it can grow when needed ?
When you do this:
List<int> = new List<int>(100);
You create a list whose capacity is 100 integers. This means that your List won't need to 'grow' until you add the 101th item. The underlying array of the list will be initialized with a length of 100.
Create an array with the number of items you want first and then convert the array in to a List.
int[] fakeArray = new int[10];
List<int> list = fakeArray.ToList();
Initializing the contents of a list like that isn't really what lists are for. Lists are designed to hold objects. If you want to map particular numbers to particular objects, consider using a key-value pair structure like a hash table or dictionary instead of a list.
If you want to initialize the list with N elements of some fixed value:
public List<T> InitList<T>(int count, T initValue)
{
return Enumerable.Repeat(initValue, count).ToList();
}
You seem to be emphasizing the need for a positional association with your data, so wouldn't an associative array be more fitting?
Dictionary<int, string> foo = new Dictionary<int, string>();
foo[2] = "string";
string [] temp = new string[] {"1","2","3"};
List<string> temp2 = temp.ToList();
The accepted answer (the one with the green check mark) has an issue.
The problem:
var result = Lists.Repeated(new MyType(), sizeOfList);
// each item in the list references the same MyType() object
// if you edit item 1 in the list, you are also editing item 2 in the list
I recommend changing the line above to perform a copy of the object. There are many different articles about that:
- String.MemberwiseClone() method called through reflection doesn't work, why?
- https://code.msdn.microsoft.com/windowsdesktop/CSDeepCloneObject-8a53311e
If you want to initialize every item in your list with the default constructor, rather than NULL, then add the following method:
public static List<T> RepeatedDefaultInstance<T>(int count)
{
List<T> ret = new List<T>(count);
for (var i = 0; i < count; i++)
{
ret.Add((T)Activator.CreateInstance(typeof(T)));
}
return ret;
}
You can use Linq to cleverly initialize your list with a default value. (Similar to David B's answer.)
var defaultStrings = (new int[10]).Select(x => "my value").ToList();
Go one step farther and initialize each string with distinct values "string 1", "string 2", "string 3", etc:
int x = 1;
var numberedStrings = (new int[10]).Select(x => "string " + x++).ToList();
A notice about IList: MSDN IList Remarks: "IList implementations fall into three categories: read-only, fixed-size, and variable-size. (...). For the generic version of this interface, see System.Collections.Generic.IList<T>
."
IList<T>
does NOT inherits from IList
(but List<T>
does implement both IList<T>
and IList
), but is always variable-size. Since .NET 4.5, we have also IReadOnlyList<T>
but AFAIK, there is no fixed-size generic List which would be what you are looking for.
This is a sample I used for my unit test. I created a list of class object. Then I used forloop to add 'X' number of objects that I am expecting from the service. This way you can add/initialize a List for any given size.
public void TestMethod1()
{
var expected = new List<DotaViewer.Interface.DotaHero>();
for (int i = 0; i < 22; i++)//You add empty initialization here
{
var temp = new DotaViewer.Interface.DotaHero();
expected.Add(temp);
}
var nw = new DotaHeroCsvService();
var items = nw.GetHero();
CollectionAssert.AreEqual(expected,items);
}
Hope I was of help to you guys.
A bit late but first solution you proposed seems far cleaner to me : you dont allocate memory twice. Even List constrcutor needs to loop through array in order to copy it; it doesn't even know by advance there is only null elements inside.
1. - allocate N - loop N Cost: 1 * allocate(N) + N * loop_iteration
2. - allocate N - allocate N + loop () Cost : 2 * allocate(N) + N * loop_iteration
However List's allocation an loops might be faster since List is a built-in class, but C# is jit-compiled sooo...
'programing tip' 카테고리의 다른 글
상위 디렉터리를 나타내는 Maven2 속성 (0) | 2020.08.23 |
---|---|
CSS를 사용한 텍스트 테두리 (텍스트 테두리) (0) | 2020.08.23 |
선택한 행을 dataTable 또는 ui : repeat 내의 commandLink에 어떻게 전달할 수 있습니까? (0) | 2020.08.23 |
Go의 기존 유형에 새 메소드를 추가하는 방법은 무엇입니까? (0) | 2020.08.23 |
div의 CSS 워드 랩핑 (0) | 2020.08.23 |