C# Language
기능적 프로그래밍
수색…
기능과 행동
Func 은 매개 변수화 된 익명 함수의 소유자를 제공합니다. 주요 유형은 입력이고 마지막 유형은 항상 리턴 값입니다.
// square a number.
Func<double, double> square = (x) => { return x * x; };
// get the square root.
// note how the signature matches the built in method.
Func<double, double> squareroot = Math.Sqrt;
// provide your workings.
Func<double, double, string> workings = (x, y) =>
string.Format("The square of {0} is {1}.", x, square(y))
액션 객체는 void 메소드와 비슷하므로 입력 유형 만 있습니다. 평가 스택에는 결과가 없습니다.
// right-angled triangle.
class Triangle
{
public double a;
public double b;
public double h;
}
// Pythagorean theorem.
Action<Triangle> pythagoras = (x) =>
x.h = squareroot(square(x.a) + square(x.b));
Triangle t = new Triangle { a = 3, b = 4 };
pythagoras(t);
Console.WriteLine(t.h); // 5.
불변성
이터 빌리티는 함수형 프로그래밍에서는 일반적이며 객체 지향 프로그래밍에서는 드물다.
예를 들어 변경 가능한 상태의 주소 유형을 만듭니다.
public class Address ()
{
public string Line1 { get; set; }
public string Line2 { get; set; }
public string City { get; set; }
}
코드 조각은 위 개체의 속성을 변경할 수 있습니다.
이제 불변의 주소 유형을 작성하십시오.
public class Address ()
{
public readonly string Line1;
public readonly string Line2;
public readonly string City;
public Address(string line1, string line2, string city)
{
Line1 = line1;
Line2 = line2;
City = city;
}
}
읽기 전용 모음을 갖고있는 것이 불변성을 존중하지 않는다는 것을 명심하십시오. 예를 들어,
public class Classroom
{
public readonly List<Student> Students;
public Classroom(List<Student> students)
{
Students = students;
}
}
객체의 사용자가 콜렉션을 변경할 수 있기 때문에 변경 불가능합니다 (요소를 추가하거나 제거 할 수 있음). 불변으로 만들려면 IEnumerable과 같은 인터페이스를 사용해야합니다. IEnumerable은 추가 할 메소드를 공개하지 않으며 ReadOnlyCollection으로 만듭니다.
public class Classroom
{
public readonly ReadOnlyCollection<Student> Students;
public Classroom(ReadOnlyCollection<Student> students)
{
Students = students;
}
}
List<Students> list = new List<Student>();
// add students
Classroom c = new Classroom(list.AsReadOnly());
불변 객체를 사용하면 다음과 같은 이점이 있습니다.
- 그것은 알려진 상태에있을 것입니다 (다른 코드는 변경할 수 없습니다).
- 스레드로부터 안전합니다.
- 생성자는 유효성 검사를위한 단일 장소를 제공합니다.
- 객체를 변경할 수 없다는 것을 알고 있으면 코드를 더 쉽게 이해할 수 있습니다.
Null 참조 피하기
C # 개발자는 많은 null 참조 예외를 처리해야합니다. F # 개발자는 Option 유형을 가지고 있기 때문에 개발자가 아닙니다. Option <> 유형 (일부는 <>을 이름으로 선호 함)은 Some 및 None 반환 유형을 제공합니다. 메소드가 널 (NULL) 레코드를 리턴하려고 할 수 있음을 명시 적으로 나타냄니다.
예를 들어, 다음을 읽고 널 값을 처리해야하는지 알 수 없습니다.
var user = _repository.GetUser(id);
가능한 null에 대해 알고 있다면이를 처리 할 상용구 코드를 도입 할 수 있습니다.
var username = user != null ? user.Name : string.Empty;
Option <>이 대신 반환되면 어떻게됩니까?
Option<User> maybeUser = _repository.GetUser(id);
이제 코드에서 None 레코드가 반환되고 Some 또는 None을 확인하는 상용구 코드가 필요하다는 것을 명시합니다.
var username = maybeUser.HasValue ? maybeUser.Value.Name : string.Empty;
다음 메서드는 Option <>을 반환하는 방법을 보여줍니다.
public Option<User> GetUser(int id)
{
var users = new List<User>
{
new User { Id = 1, Name = "Joe Bloggs" },
new User { Id = 2, Name = "John Smith" }
};
var user = users.FirstOrDefault(user => user.Id == id);
return user != null ? new Option<User>(user) : new Option<User>();
}
다음은 Option <>의 최소 구현입니다.
public struct Option<T>
{
private readonly T _value;
public T Value
{
get
{
if (!HasValue)
throw new InvalidOperationException();
return _value;
}
}
public bool HasValue
{
get { return _value != null; }
}
public Option(T value)
{
_value = value;
}
public static implicit operator Option<T>(T value)
{
return new Option<T>(value);
}
}
위의 설명을 위해 avoidNull.csx 는 C # REPL을 사용하여 실행할 수 있습니다.
명시된 바와 같이, 이것은 최소한의 구현입니다. "어쩌면"NuGet 패키지를 검색하면 여러 좋은 라이브러리를 얻을 수 있습니다.
고차 함수
고차 함수는 다른 함수를 인수로 사용하거나 함수를 반환하는 함수입니다.
이것은 LINQ Where 절에 조건자를 전달할 때와 같이 lambda를 사용하여 일반적으로 수행됩니다.
var results = data.Where(p => p.Items == 0);
Where () 절은 상당한 유연성을 제공하는 많은 다른 술어를받을 수 있습니다.
메소드를 다른 메소드로 전달하는 것은 전략 디자인 패턴을 구현할 때도 나타납니다. 예를 들어, 런타임시 요구 사항에 따라 다양한 Sorting 메서드를 선택하여 개체의 Sort 메서드에 전달할 수 있습니다.
불변의 콜렉션
System.Collections.Immutable
NuGet 패키지는 불변의 컬렉션 클래스를 제공합니다.
항목 생성 및 추가하기
var stack = ImmutableStack.Create<int>();
var stack2 = stack.Push(1); // stack is still empty, stack2 contains 1
var stack3 = stack.Push(2); // stack2 still contains only one, stack3 has 2, 1
빌더를 사용하여 만들기
특정 불변의 콜렉션에는 큰 불변 인스턴스를 저렴하게 구축하는 데 사용할 수있는 Builder
내부 클래스가 있습니다.
var builder = ImmutableList.CreateBuilder<int>(); // returns ImmutableList.Builder
builder.Add(1);
builder.Add(2);
var list = builder.ToImmutable();
기존 IEnumerable에서 만들기
var numbers = Enumerable.Range(1, 5);
var list = ImmutableList.CreateRange<int>(numbers);
모든 불변의 콜렉션 유형 목록 :
-
System.Collections.Immutable.ImmutableArray<T>
-
System.Collections.Immutable.ImmutableDictionary<TKey,TValue>
-
System.Collections.Immutable.ImmutableHashSet<T>
-
System.Collections.Immutable.ImmutableList<T>
-
System.Collections.Immutable.ImmutableQueue<T>
-
System.Collections.Immutable.ImmutableSortedDictionary<TKey,TValue>
-
System.Collections.Immutable.ImmutableSortedSet<T>
-
System.Collections.Immutable.ImmutableStack<T>