ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [C# / .NET] Java와 다른 문법
    카테고리 없음 2022. 4. 7. 22:04

    Java와 다른 것 위주로 기술

    로컬함수

    로컬함수는 메소드 안에서 선언되고, 선언된 메소드 안에서만 사용되는 특별한 함수

    클래스의 멤버가 아니기 때문에 메소드가 아니라 함수라고 부름

    class SomeClass
    {
    	public void SomeMethod()
        {
        	int count = 0;
            SomeLocalFunction(1,2); //로컬 함수 호출
            
            void SomeLocalFunction(int a, int b) //로컬 함수 선언
            {
            	//Do Some Work
                Console.WriteLine($"count : {++count}"); //로컬 함수는 자신이 속한 메소드의 지역 변수를 사용할 수 있음
            }
        }
    }

     

    선택적 인수

    메소드의 기본변수는 기본값을 가질 수 있음 

    void MyMethod(int a, int b = 0)
    {
    	Console.WriteLine("{0}, {1}", a, b);
    }

    이와 같이 기본 값을 가진 매개변수는 메소드 호출시 해당 인수를 생략할 수 있음

    MyMethod(3); 

    MyMethod(3, 4);

     

     

    가변 개수의 인수

    프로그래밍을 하다 보면 그저 인수의 '개수' 개수가 다르다는 이유만으로 똑같은 메소드를 여러 가지 버전으로 오버로딩하고 싶을 때가 많음 

    이런 경우를 위해 C#은 '가변 개수의 인수'라는 기능을 제공함 

    가변 개수의 인수란, 그 개수가 유연하게 변할 수 있는 인수를 뜻함 

    이것을 이용하면 다음과 같이 입력되는 모든 인수의 합을 구하는 Sum() 메소드를 오버로딩하지 않고도 구현할 수 있음

    int total = 0;
    
    total = Sum(1);
    total = Sum(1,2);
    total = Sum(1,2,3,4);
    total = Sum(1,2,3,4,5,6);
    total = Sum(1,2,3,4,5,6,7,8);

     

    가변 개수의 인수는 params 키워드와 배열을 이용해서 선언함 

    다음은 가변 개수의 인수를 이용해서 모든 합을 구해 반환하는 Sum() 메소드의 구현임 

    이렇게 구현한 메소드는 앞에서 본 코드에서처럼 인수의 개수를 달리해서 호출할 수 있음

    int Sum( params int[] args ) 
    {
    	int sum = 0;
        
        for(int i=0; i<args.Length; i++){
    		sum += args[i];    
        }
        
        return sum;
    }

     

     

    메소드의 결과를 참조로 반환하기

    참조 반환값을 이용하면 메소드의 호출자로 하여금 반환받은 결과를 참조로 다룰 수 있도록 함

    class SomeClass{
    	int SomeValue = 10;
        
        public ref int SomeMethod(){
        	return ref SomeValue; 
        }
    }
    
    Main ..(){
    	//ref 사용 안 하는 예제 
        SomeClass obj = new SomeClass();
        int result = obj.SomeMethod();
        
        //ref 사용하는 예제
        SomeClass obj = new SomeClass();
        ref int result = ref obj.SomeMethod();
    }
    using System; 
    
    namespace RfReturn {
    	class Product{    	
            private int price = 100;
            
            public ref int GetPrice(){
            	return ref price;
            }
            
            public void PrintPrice(){
            	Console.WirteLine($"Price : {price}");            
            }
        }
        
        class MainApp{
        	static void Main(String[] args){
            	Product carrot = new Product();
                ref int ref_local_price = ref carrot.GetPrice();
                int normal_local_price = carrot.GetPrice(); 
                
                carrot.PrintPrice();
                Console.WriteLine($"Ref Local Price : {ref_local_price}"); 
                Console.WirteLine($"Normal Local Price : {normal_local_price}");
                
                ref_local_price = 200;
                
                carrot.PrintPrice(); 
                Console.WriteLine($"Ref Local Price : {ref_local_price}"); 
                Console.WirteLine($"Normal Local Price : {normal_local_price});
                
            }
        }
    }
    
    
    /*
    ========== 결과 ==========
    
    Price : 100
    Ref Local Price : 100
    Normal Local Price : 100
    
    Price : 200
    Ref Local Price : 200
    Normal Local Price : 100
    */

     

     

    goto

    goto? 점프문 

     

    goto 레이블;

    레이블 : 

    //이어지는 코드

     

    {
    	Console.WriteLine(" 1 "); 
        
    	goto JUMP;
        
    	Console.WriteLine(" 2 ");
    	Console.WriteLine(" 3 ");
        
     	JUMP:
    	Console.WriteLine(" 4 ");
    }
    
    /*
    ===== 결과 =====
    1
    4
    */

     

    foreach

    int[] arr = new int[]{0,1,2,3,4};
    
    foreach(int a in arr) //java는 ? for(int a : arr){}
    {
    	Console.WriteLIne(a);
    }

     

     

    switch식 

    Swtich문이 아닌 switch식

    //switch문 
    int score = Console.ReadLine();
    string grade;
    
    switch(score)
    {
    	case 90:
        	grade = "A";
            break;
        case 80:
        	grade = "B";
            break;
        case 70:
        	grade = "C";
            break;
        case 60:
        	grade = "D";
        	break;
        default:
        	grade = "F";        
    }
    
    //switch식
    int score = Console.ReadLine();
    string grade = score switch{
    	90 => "A",
    	80 => "B",
    	70 => "C",
    	60 => "D",
    	_ => "F"
    };
    
    //switch식 - when 절을 활용
    bool repeated = true;
    string grade = score switch{
    	90 when repeted == true => "B+",
    	90 => "A",
    	80 => "B",
    	70 => "C",
    	60 => "D",
    	_ => "F"
    }

     

    상속

    class Base
    {
    	int 
    	public void BaseMethod()
        {
        	Console.WriteLine("BaseMethod");
        }
    }
    
    class Derived : Base
    {
    	//Derived 클래스는 Base 클래스를 상속했으므로 BaseMethod()를 가짐
        
        public void DerivedMethod()
        {
        	base.BaseMethod(); //java super 같은
        }
    }
    class Base
    {
    	protected String Name;
        public Base(string Name)
        {
        	this.Name = Name;
        }
    }
    
    class Derived : Base
    {  
        public DerivedMethod(string Name) : base(Name) //Base(string Name) 호출
        {
        	base.BaseMethod(); //java super 같은
        }
    }
    using System;
    
    namespace Inheritance
    {
    	class Base
        {
        	protected String Name; 
            public Base(string Name)
            {
            	this.Name = Name;
                Console.WriteLine($"{this.Name}.Base()");
            }
            
            ~Base()
            {
            	Console.WriteLine($"{this.Name}.~Base()");
            }
            
            public void BaseMethod()
            {
            	Console.WriteLine($"{Name}.BaseMethod()");
            }
        }
        
        class Derived : Base
        {
        	public Derived(string Name) : base(Name)
            {
            	Console.WriteLine($"{this.Name}.Derived()");
            }
            
            ~Derived()
            {
            	Console.WriteLine($"{this.Name}.~Derived()");
            }
            
            public void DerivedMethod()
            {
            	Console.WriteLine($"{Name}.DerivedMethod()");
            }
        }
        
        class MainApp
        {
        	static void Main(string[] args)
            {
            	Base a = new Base("a");
                a.BaseMethod();
                
                Console.WriteLine();
                
                Derived b = new Derived("b");
                b.BaseMethod();
                b.DerivedMethod();
            }
        }
    }
    
    
    /*
    ======== 결과 ========
    a.Base()
    a.BaseMethod()
    
    b.Base()
    b.Derived()
    b.BaseMethod()
    b.DerivedMethod()
    
    */

    상속 봉인도 가능 

    sealed class Base{ ... }

    class Derived : Base { ... } => 컴파일 에러남

     

    형식 변환을 위한 연산자 is, as

    • is : 객체가 해당 형식에 해당하는지 검사하여 그 결과를 bool 값으로 반환함 (java의 instanceof 와 같아 보임)
    Base bs = new Derived();
    Derived dv;
    
    if(bs is Derived)
    {
    	dv = (Derived)bs;
    }

     

    • as : 형식 변환 연산자와 같은 역할을 함. 다만 형식 변환 연산자가 변환에 실패하는 경우 예외를 던지는 반면에 as 연산자는 객체 참조를 null로 만든다는 것이 다름.
    Base bs2 = new Derived();
    
    Derived dv2 = bs2 as Derived; 
    if(dv2 != null) //bs2가 Derived 형식 변환에 실패했다면 null이 됨, 하지만 이코드에서는 안전하게 형식 변환이 이루어짐
    {
    	Console.WriteLine("complete"); 
    }

     

    오버라이딩(Overriding)

    자식 클래스에서 부모 클래스의 메소드를 오버라이딩 하기 위해서는 부모 메소드에 virtual을 명시해주어야 하며,

    자식 메소드에는 override를 명시해주어야 함 

    class Base{
    	public virtual void UtilMethod(){
        	Console.WriteLine("Base Util Method()");
        }
    }
    
    class Derived{
    	public override void UtilMethod(){
        	Console.WriteLine("Derived Util Method()");
        }
    }

    const vs readonly

    • 상수 : 변하지 않는 값 
    • 변수 : 자유롭게 변하는 값
    • 읽기 전용 : 상수와 변수 사이 그 중간 어딘가
    class D {
    	private readonly int r;
        private const int i ; //컴파일 에러 발생 => 반드시 선언과 동시에 초기화를 해주어야 함 
     	
        public D(int n){
        	r = n; //생성자 안에서만 초기화가 가능
        }
        
        public Method(int n){
        	r = n; //컴파일 에러
        }
    }

     

    중첩 클래스

    class A{
        class B{
        }
    }

    중첩클래스를 쓰는 이유? 

    • 클래스 외부에 공개하고 싶지 않은 형식을 만들고자 할 때
    • 현재 클래스의 일부분처럼 표현할 수 있는 클래스를 만들고자 할 때

     

    프로퍼티

    java에서는 class의 private 변수에 접근하기 위해 보통 아래와 같이 사용했었음 

    class MyClass{
    	
        private int myField;
        public int GetMyField() { return myField; }
        public void SetMyField(int num) { myField = num; }
        
    }

    그런데 C#의 프로퍼티를 활용하면 아래와 같이 간단하게 표현 할 수 있고, '='을 통해 바로 변수 값을 설정할 수 있음

    class 클래스 이름 
    {
        데이터형식 필드이름;
        접근한정자 데이터형식 프로퍼티이름
        {
        	get
            {
            	return 필드이름;
            }
            
            set
            {
            	필드이름 = value;
            }
        }
    }

    프로퍼티 선언 문법에서 get {...} set {...} 을 일컬어 접근자라고 함 

    value 키워드는 선언한 적은 없지만, c# 컴파일러는 set 접근자의 암묵적 매개변수로 간주함

    class MyClass
    {
    	private int myField;
    	public int MyField
    	{
    	get
    	{
    		return myField;
    	}
    
    	set
    	{
    		myField = value;
    	}
    	}
    }
    
    ...
    
    MyClass obj = new MyClass();
    obj.MyField = 3;

     

    C# 3.0부터는 자동 구현 프로퍼티가 가능함 

    public class NameCard
    {
        public String Name
        {
        	get;set;
        }
    }
    
    ..
    
    //호출시에
    NameCard nc = new NameCard
    {
    	Name = "영국너구리"
    }

     

    더불어 C# 7.0부터는 자동 구현 프로퍼티를 선언함과 동시에 초기화를 수행할 수 있음 

    public class NameCard
    {
        public string Name{ get; set; } = "Unknown";
        public string PhoneNumber{ get; set; } = "000-0000";
    }

    댓글

Designed by Tistory.