[ 학습 흐름 ]
[ 학습 흐름 ]
- 메소드 알아보기
- return
- 매개변수와 인자
- 참조에 의한 매개변수 전달
- 출력 전용 매개변수
- 메소드 오버로딩
- 가변 개수의 인수
- 명명된 인수
- 선택적 인수
[ 메소드란 ]
[ 메소드 ]
메소드
- 일련의 코드를 하나로 묶은 것 . C/C++에서는 함수 / 파스칼에서는 프로시저
- 메소드가 함수 , 프로시저 , 서브루틴과 다른점은 클래스 내부에 존재한다는 점 .
class 클래스 이름
{
[한정자] [반환현식] [메소드 이름] ( 매개변수 목록 )
{
//실행 코드
//실행 코드
return 메소드 결과;
}
}
매개 변수와 반환 형식
- 매개변수는 제품을 만들기 위해 기계(메서드)에 넣는 재료
- 매서드의 반환형식은 제품의 규격
메소드의 호출 과정
- 호출자가 메소드를 호출하면서 인수를 넘긴다
- 인수는 메소드의 매개 변수에 입력
- 호출을 받은 메소드는 매개변수를 이용하여 계산 수행후 결과를 호출자에게 반환
매개변수와 인수
- 매개변수는 메소드가 호출자에게 전달받은 값을 받는 변수
- 인수는 호출자가 매개변수에 넘기는 값
using System;
using System.Collections.Generic;
using System.Net.NetworkInformation;
namespace Method;
class Calculator
{
public static int Plus(int a,int b)
{
return a + b;
}
public static int Minus(int a, int b)
{
return a - b;
}
}
class MainApp
{
//프로그램 실행이 시작되는 곳
static void Main(string[] args)
{
int result = Calculator.Plus(3, 4);
Console.WriteLine(result);
result=Calculator.Minus(5, 2);
Console.WriteLine(result);
}
}
void 반환형식
- 모든 메소드들이 결과를 반환하는건 아님 ex) Console.WriteLine()
- 반환 형식에 void를 넣어주면 됨
static 한정자
- 메소드나 필드가 클래스의 인스턴스가 아닌 클래스 자체에 소속되도록 지정하는 한정자
- 해당 클래스의 인스턴스를 만들지 않고도 메소드를 호출 할 수 있다 .
[ return에 관하여 ]
[ return ]
메소드
- return 문은 점프문의 한 종류로 프로그램의 흐름을 호출자에게 돌려놓는다 .
- 메소드 중간에 호출되어 메소드를 종결 , 프로그램의 흐름을 호출자에게 돌려준다 .
using System;
namespace Return;
class MainApp
{
static int Fibonacci(int n)
{
if (n < 2)
return n;
else
return Fibonacci(n-1)+Fibonacci(n-2);
}
static void PrintProfile(string name,string phone)
{
if(name=="")
{
Console.WriteLine("이름을 입력해주세요");
return;
}
Console.WriteLine($"Name : {name} Phone : {phone}");
}
//프로그램 실행이 시작되는 곳
static void Main(string[] args)
{
Console.WriteLine($"10번째 피보나치 수 : {Fibonacci(10)}");
PrintProfile("", "123-4567");
PrintProfile("박상현", "456-789");
}
}
[ 매개변수에 대하여 ]
[ 매개변수의 전달 ]
매개 변수의 전달
int x =3;
int y=5;
int result = Calculator.Plus(x,y);
- 위 코드에서 x와 y는 실제로 Calculator.Plus 메서드에 들어가지 않는다 .
- 매개변수도 근본적으로 변수기에 메소드 외부로부터 메소드 내부로 데이터를 전달받는 매개체 역할을 할 뿐이다 .
- 즉 ,그 데이터가 참조든 값이든 내부 데이터가 복사될 뿐이다 .
- x와 Plus 메서드의 매개변수a는 같은 데이터(3)를 가지고 있지만 별개의 메모리 공간을 사용한다
값에 의한 전달
public static void Swap(int a,int b)
{
int temp=b;
b=a;
a=temp;
}
- 메소드를 호출할 때 데이터를 복사해서 매개변수에 넘기는 것을 값에 의한 전달이라 한다 .
참조에 의한 전달
- 매개변수가 메소드에 넘겨진 원본 변수를 직접 참조한다 .
- 메소드 안에서 매개변수를 수정하면 원본 변수에 수정이 이루어진다 .
- ref 키워드를 매개변수 앞에 붙이면 참조에 의한 전달이 이루어진다 .
public static void Swap(ref int a,ref int b)
{
int temp=b;
b=a;
a=temp;
}
//호출시도 ref 키워드를 매개변수 앞에 붙여준다
Swap(ref x,ref y);
using System;
namespace Return;
class MainApp
{
static void Swap(ref int a,ref int b)
{
int temp = b;
b = a;
a = temp;
}
//프로그램 실행이 시작되는 곳
static void Main(string[] args)
{
int a = 3;
int b=4;
Console.WriteLine($"a : {a} b : {b}");
Swap(ref a,ref b);
Console.WriteLine($"a : {a} b : {b}");
}
}
[ 메소드의 결과를 참조로 반환하기 ]
[ 참조 반환값 ]
- 메소드의 호출자로 하여금 반환받은 결과를 참조로 다룰 수 있도록 한다 .
class SomeClass
{
int SomeValue=10;
//ref 키워드로 메소드를 한정한다
public ref int SomeMethod()
{
//return문을 사용할 때 ref 키워드를 반환할 필드/객체 앞에 붙여준다 .
return ref SomeValue;
}
}
//호출자가 특별한 키워드를 사용하지 않는 이상 값을 반환하는 평범한 메소드처럼 동작
SomeClass obj = new SomeClass();
int result = obj.SomeMethod();
//반환 결과를 호출자가 참조로 넘겨받고 싶다면 ref 키워드 사용
SomeClass obj = new SomeClass();
ref int result = ref obj.SomeMethod(); //참조 반환 결과를 담는 result는 참조 지역변수라 부른다
using System;
namespace RefReturn;
class Product
{
private int price = 100;
public ref int GetPrice()
{
return ref price;
}
public void PrintPrice()
{
Console.WriteLine($"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.WriteLine($"Normal Local Price : {normal_local_price}");
ref_local_price = 200;
carrot.PrintPrice();
Console.WriteLine($"Ref Local Price : {ref_local_price}");
Console.WriteLine($"Normal Local Price : {normal_local_price}");
}
}
[ 출력 전용 매개변수 ]
[ 두개 이상의 결과를 요구하는 메서드 ]
- 나눗셈을 구현할 때 제구와 피제수를 매개변수로 넘겨 받고 결과는 몫과 나머지로 반환해야 한다 .
- 위와 같이 두개 이상의 결과를 요구하는 메서드가 있다면 어떻게 구현해야 할까?
[ ref 키워드를 이용 ]
void Divide(int a,int b,ref int quotient,ref int remainder)
{
quotient = a/b;
remainder = a%b;
}
- ref 키워드를 이용, 여러가지 결과를 메서드에서 얻어올 수 있다 .
- 다만 , 안전장치가 없다 . ex ) 메소드가 해당 매개변수에 결과를 저장하지 않아도 컴파일러는 경고하지 않는다 .
[ out 키워드를 이용 ]
사용법
void Divide(int a,int b,out int quotient,out int remainder)
{
quotient = a/b;
remainder = a%b;
}
- out 키워드를 이용한 "출력 전용 매개변수"는 안전한 방법으로 위와 같은 일을 하게 해준다 .
out 키워드의 장점
- 메소드가 해당 매개변수에 값을 저장하지 않으면 컴파일러가 에러 메시지를 출력한다 .
- 호출자는 초기화 하지 않은 지역변수를 메소드의 out 매개변수로 넘길 수 있다 (할당을 보장하기에)
- 컴파일러를 통해 결과를 할당하지 않는 버그가 만들어질 가능성을 제거할수 있기에 out 키워드를 사용한다 .
- 출력 전용 매개변수는 매개변수 목록 안에서 즉석으로 선언 할 수 있다 .
using System;
namespace UsingOut;
class MainApp
{
static void Divide(int a,int b,out int quotient,out int remainder)
{
quotient = a / b;
remainder=a%b;
}
static void Main(string[] args)
{
int a = 20;
int b = 3;
Divide(a, b, out int c, out int d);
Console.WriteLine($"a : {a} b : {b} a/b : {c} a%b : {d}");
}
}
[ 메소드 오버로딩 ]
[ 메소드 오버로딩 ]
- 하나의 메소드 이름에 여러개의 구현을 올리는 것
- 컴파일러는 메소드 호출시 반환형식은 묻지도 않고 매개변수의 수와 형식만 분석하여 어느 버전이 호출될지를 찾아준다
- 컴파일 타임에 이루어지기에 성능저하는 걱정하지 않아도 됨
- 이름에 대한 고민을 줄여주고 , 코드를 일관성 있게 유지한다 .
static int Plus(int a,int b)
{
return a+b;
}
static int Plus(int a,int b,int c)
{
return a+b+c;
}
static double Plus(double a,double b)
{
return a+b;
}
static double Plus(double a,double b,double c)
{
return a+b+c;
}
[ 가변 개수의 인수 ]
[ 가변개수의 인수 ]
- 인수의 개수가 다르다는 이유만으로 같은 메서드를 여러 버전으로 오버로딩 하고 싶을 수 있다 .
- 가변개수의 인수는 그 개수가 유연하게 변할 수 있는 인수를 말한다 .
- params 키워드와 배열을 이용하여 선언한다 .
- 메소드 오버로딩은 매개변수의 형식/개수가 다를때 사용한다
- 반면 , 인수의 형식은 같으나 개수가 유연해야 한다면 가변개수의 인수를 사용한다 .
using System;
namespace UsingParams;
class MainApp
{
static int Sum(params int[] args)
{
Console.WriteLine("Summing ... ");
int sum = 0;
for(int i=0;i<args.Length;i++)
{
if (i > 0)
Console.Write(",");
Console.Write(args[i]);
sum += args[i];
}
Console.WriteLine();
return sum;
}
static void Main(string[] args)
{
int sum = Sum(3,4,5,6,7,8,9,10);
Console.WriteLine($"Sum: {sum}");
}
}
[ 명명된 인수 ]
[ 명명된 인수 ]
- 메소드 호출시 매개변수 목록 중 어느 매개변수에 데이터를 할당할지 지정하는 것은 순서이다 .
- 명명된 인수는 인수의 이름에 근거해서 데이터를 할당 할 수 있다 .
- 메소드 호출시 인수의 이름뒤에 콜론을 붙여 할당할 데이터를 넣어주면 된다 .
- 이는 코드의 가독성을 높여준다 .
static void PrintProfile(strin name,string phone)
{
Console.WriteLine($"Name : {name} Phone : {phone}");
}
static void Main(string[] args)
{
PrintProfile(name:"Yeo",phone:"10122");
}
[ 선택적 인수 ]
[ 선택적 인수 ]
- 메소드의 매개변수는 기본값을 가질 수 있다 .
- 기본값을 가진 매개변수는 메소드 호출시 해당 인수를 생략 할 수 있다.
- 선택적 인수는 항상 필수 인수의 뒤에 와야 한다 .
- 모호함의 문제는 명명된 인수와 함께 사용해 해결 할 수 있다 .
static void PrintProfile(strin name,string phone="")
{
Console.WriteLine($"Name : {name} Phone : {phone}");
}
static void Main(string[] args)
{
PrintProfile(name:"Yeo",phone:"10122");
PrintProfile(name:"KIM");
}
[ 메소드 오버로딩 VS 선택적 매개변수 ]
void MyMethod(string arg0="",string arg1="")
{
Console.WriteLine(A);
}
void MyMethod()
{
Console.WriteLine(B);
}
- 위와 같이 메소드 오버로딩과 선택적 매개변수가 같이 사용되면 0점자리 코드이다 .
- 논리는 동일하되 매개변수가 다른경우는 선택적 인수를 사용하자
- 매개변수에 따라 논리도 바뀐다면 오버로딩을 사용하자
[ 로컬 함수 ]
[ 로컬 함수 ]
- 메소드 안에서 선언되고 , 선언된 메소드 안에서만 사용되는 특별한 함수
- 클래스의 멤버가 아니기에 메소드가 아닌 함수라 불린다 .
- 로컬함수는 자신이 속한 메소드의 지역변수를 사용 할 수 있다 .
- 메소드 밖에서는 쓸 일 없는 반복적인 작업을 하나의 이름아래 묶는데 제격이다 .(람다식과 더불어 코드를 간추릴 옵션)
using System;
namespace LocalFunction;
class MainApp
{
static string ToLowerString(string input)
{
var arr = input.ToCharArray();
for(int i=0;i<arr.Length; i++)
{
arr[i] = ToLowerChar(i);
}
char ToLowerChar(int i)
{
//ASCII : A _Z 는 65 ~ 90 / a -z 는 97 ~ 122
if (arr[i] < 65 || arr[i] > 90)
return arr[i];
else
return (char)(arr[i]+32);
}
return new string(arr);
}
static void Main(string[] args)
{
Console.WriteLine(ToLowerString("HELLO"));
Console.WriteLine(ToLowerString("GOOD MORNING"));
}
}
'C# > 이것이 C#이다' 카테고리의 다른 글
[ 이것이 C#이다 ] Chapter 08 . 인터페이스와 추상 클래스 (2) | 2024.03.12 |
---|---|
[ 이것이 C#이다 ] Chapter 07 . 클래스 (0) | 2024.03.06 |
[ 이것이 C#이다 ] Chapter 05 . 코드의 흐름 제어하기 (0) | 2024.02.28 |
[ 이것이 C#이다 ] Chapter 04 . 데이터를 가공하는 연산자 (0) | 2024.02.27 |
[ 이것이 C#이다 ] Chapter 03 . 데이터 보관하기 (0) | 2024.02.15 |