C#

C# in 키워드

kark 2024. 7. 14. 23:15
728x90

in 키워드는 여러 맥랙에 사용되며 각 맥락마다 의미가 다르다.

in 키워드를 사용하는 대표적인 예 : 매개변수 , foreach 문 , 제네릭 타입 매개변수

 

① 메서드의 매개변수에서 사용

메서드 매개변수에서 사용되는 in 키워드는 매개변수를 읽기전용으로 전달하기 위해 사용된다.

이때 전달되는 매개변수는 참조를 전달하게 된다.

public class TestClass
{
    int _myData;

    public void Test(in int m_data)
    {
        _myData = m_data; // 가능
        Console.WriteLine(m_data); // 가능
        
        m_data = 3; // 불가능 , 컴파일 에러
    }
}

 

매개변수가 값형식인데 in 키워드를 사용하는 때

매개변수를 전달할때는 전달하고자 하는 데이터의 값을 복사하는 과정이 발생된다.

 

만약 데이터가 큰 경우(struct 구조체)

구조체 내부의 모든 데이터를 복사하는 과정을 생략하고

구조체 객체의 참조를 전달하는 과정으로 효율성을 높일 수 있다.

 

또한 해당 키워드를 통해 데이터가 변경되지 않도록 보장하여 안전성을 높일 수 있다.

만약 참조형식의 전달의 경우 참조 자체가 변경되지 않게 보장할 수 있다.

 

하지만 전달된 객체 내부의 멤버변수는 변경될 수 있다.

 

② foreach 문에서의 사용

foreach 문에서 in 키워드는 컬렉션의 각 요소를 순회하는데 사용되며

이때 컬렉션의 각 요소를 읽기전용으로 접근하게 되며 각 요소의 값을 변경할 수 없다.

 

왜 for 반복문과 달리 읽기 전용인 이유는 순회의 안정성을 위함이다.

 

③제네릭 타입 매개변수

제네릭 타입 매개변수의 공변성과 반공변성은 제네릭 인터페이스, 델리게이트 타입 매개변수가

상속 관계에 따라 유연하게 동작할 수 있게 한다.

 

이를 활용하여 재사용성과 유연성을 높일 수 있다.

 

https://kark.tistory.com/78

 

C# 가변성,공변성, 반공변성, 불공변성

공변성과 반공변성은 제네릭 타입 시스템에 타입의 상속 관계에 따라 제네릭 타입변환을 허용하는 특성을 의미한다. string[] strArr = new string[5];object[] objArr = strArr;위의 코드처럼 형변환이 가능한

kark.tistory.com

 

나름 정리해본다고 몇일 고민해본 내용이다.

 

 

공변성

제네릭 타입 매개변수가 반환타입으로 사용될때 구체적인 타입을 더 일반적인 타입으로 변환할수 있게한다.

이는 out 키워드를 사용하여 지정하며 주로 데이터 생산자 역할을 하는 상황에 유용하다.

 

public interface IProducer<out T>
{
    T Produce();
}

public class Animal { }
public class Dog : Animal { }

public class DogProducer : IProducer<Dog>
{
    public Dog Produce()
    {
        return new Dog();
    }
}

public class Example
{
    public static void Main()
    {
        IProducer<Dog> dogProducer = new DogProducer();
        IProducer<Animal> animalProducer = dogProducer; // 공변성으로 인해 가능

        Animal animal = animalProducer.Produce();
        Console.WriteLine(animal.GetType().Name); // 출력: Dog
    }
}

 

IProducer<out T>는 공변성을 갖고 DogProducer 클래스의 인스턴스인

dogProducer 가 IProducer<Animal> 로 변환할 수 있다.

 

 

반공변성

제네릭 타입 매개변수가 입력 타입으로 사용될때 일반적인 타입을 구체적인 타입으로 변환할 수 있게한다.

 

public interface IConsumer<in T>
{
    void Consume(T item);
}

public class Animal { }
public class Dog : Animal { }

public class AnimalConsumer : IConsumer<Animal>
{
    public void Consume(Animal item)
    {
        Console.WriteLine(item.GetType().Name);
    }
}

public class Example
{
    public static void Main()
    {
        IConsumer<Animal> animalConsumer = new AnimalConsumer();
        IConsumer<Dog> dogConsumer = animalConsumer; // 반공변성으로 인해 가능

        dogConsumer.Consume(new Dog()); // 출력: Dog
    }
}

 

IConsumer<in T> 는 반공변성을 갖고 AnimalConsumer 클래스 인스턴스인

animalConsumer 가 IConsumer<Dog>로 변환할 수 있다.