List 객체의 item 값 변경 문의

internal class Program
{
	static void Main(string[] args)
	{
		A a = new A();

		Console.WriteLine(a.GetCount());

		a.SetByte();
		var b0 = a.GetByte(0);
		var b1 = a.GetByte(1);

		Console.WriteLine(b0 is null);
		Console.WriteLine(b1 is null);

		Console.Read();
	}

}

public class A
{
	protected virtual List<byte[]?> LM => new() { null, null, };

	public int GetCount()
		=> LM.Count;

	public void SetByte()
	{
		LM[0] = new byte[2] { 0x01, 0x02, };
		LM[1] = new byte[2] { 0x03, 0x04, };
	}

	public byte[]? GetByte(int idx)
		=> LM[idx];
}

이 코드에서 b0와 b1이 항상 null이 됩니다.
LM은 상속 받는 클래스마다 초기값이 달라져야 하고 (그래서 virtual property로 만들었습니다.), 런타임에도 값을 변경해야 합니다. 어떻게 코드를 변경해야 할까요?

LM {get; set;} = new() { null, null, }; 로 바꾸면 될 거 같아요 LM => new() { null, null, };은 getter만 정의한거라 LM을 호출할 때마다 new() {null, null,}을 반환하겟다는거랑 같은 말입니다. 즉 setter가 없는 LM { get { return new() { null, null, }; } } 와 같은거죠.

2 Likes

감사합니다.
setter가 객체 자체를 변경하는게 아니라 객체의 item을 변경할 때도 있어야 하나보네요.

protected List<byte?> _list = new List<byte?> { null, null };
protected virtual List<byte?> LM => _list;

*phind님 충성충성.

@태현짱와우 님 말씀처럼 property 잘못써서 생긴 결과고

약간 java 코드 같아서 cs 코드로 바꿔 봤습니다.

internal class Program
{
    static void Main(string[] args)
    {
        A a = new A();

        Console.WriteLine(a.Count);

        //a[0] = [0x01, 0x02];
        //a[1] = [0x03, 0x04];
        // or
        // a.Init();

        Console.WriteLine(a[0] is null);
        Console.WriteLine(a[1] is null);

        Console.Read();
    }

}

public class A
{
    public A()
    {
        LM[0] = [0x01, 0x02];
        LM[1] = [0x03, 0x04];
    }
    public void Init()
    {
        LM[0] = [0x01, 0x02];
        LM[1] = [0x03, 0x04];
    }
    protected virtual List<byte[]?> LM { get; } = [null, null];

    public int Count => LM.Count;

    public byte[]? this[int i]
    {
        get => LM[i];
        set => LM[i] = value;
    }
}

객체를 변경하는게 아니라 초기에 생성한 객체의 item을 변경하는건데 setter가 필요한가요?

접근자인 "속성"을 생성자로 사용하고 있기에 발생한 혼란입니다.

문법적으로 아무런 문제가 없어도, 그 의미가 생성자인 경우 아래와 같이 메서드로 정의하는 것이 질문과 같은 혼란을 막을 수 있습니다.

protected virtual List<byte[]?> NewList() => new() { null, null, };

닷넷의 많은 라이브러리는 이러한 패턴을 따르고 있습니다. 예를 들면,

var id = Guid.NewGuid();

질문의 속성을 메서드로 변경하면, 클래스 A 코드의 이상함이 쉽게 드러납니다.

public class A
{
    protected virtual List<byte[]?> NewList() => 
        [null, null,];

    public int GetCount() => 
        NewList().Count;

    public void SetByte()
    {
        NewList()[0] = [0x01, 0x02,];
        NewList()[1] = [0x03, 0x04,];
    }

    public byte[]? GetByte(int idx) => 
        NewList()[idx];
}

물론, 이 코드는 @jrchs 님이 의도한 코드는 아닐 것입니다.

아마도 문맥이 완전히 다른 초기화와 설정을 같은 것으로 취급하고 있는 듯합니다.

setter 가 없어도, 초기화는 가능합니다.

2 Likes