33

C #에서는 다음과 같은 작업을 수행 할 수 있습니다.

var a = new {name = "cow", sound = "moooo", omg = "wtfbbq"};

파이썬에서는 다음과 같은 것을 할 수 있습니다.

a = t(name = "cow", sound = "moooo", omg = "wtfbbq")

기본적으로는 아니지만 클래스를 구현하는 것은 간단합니다.t그것을 할 수있게 해줍니다. 필자는 Python을 사용하여 작업 할 때 정확하게 그랬습니다. 인덱스가 아니라 이름으로 구성 요소에 액세스 할 수 있기를 원하는 곳에 작은 컨테이너를 배치하는 것이 매우 편리하다는 것을 알게되었습니다.

세부 사항 이외에, 그들은 그들이 제공하는 틈새 시장에서 튜플과 기본적으로 동일합니다.

특히, 지금이 C #코드를보고 있습니다.

routes.MapRoute(
            "Default", // Route name
            "{controller}/{action}/{id}", // URL with parameters
            new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
        );

그리고 그것은 F #equivalent

type Route = { 
    controller : string
    action : string
    id : UrlParameter }

routes.MapRoute(
    "Default", // Route name
    "{controller}/{action}/{id}", // URL with parameters
    { controller = "Home"; action = "Index"; id = UrlParameter.Optional } // Parameter defaults
  )

오히려 짜증나는 것은 말할 것도없고 장황하고 반복적입니다. F #에서 이런 종류의 구문에 얼마나 가까이 다가 갈 수 있습니까? 나는 어떤 농구 (심지어 타오르는 농구까지도)를 뛰어 다니는 것을 좋아하지 않는다. 지금 그것이 나에게 이런 식으로 드레 이닝하는데 유용한 것을 줄 것이라는 것을 의미한다면 지금.


  • 익명 형식은 C #의 튜플이 아니라는 것을 언급하기 위해 튜플 클래스가 있습니다. - Ben Robinson

4 답변


24

나는 그것을하기가 더 쉽다는 것을 안다.

let route = routes.MapRoute(
    "Default", // Route name
    "{controller}/{action}/{id}" // URL with parameters
    )
route.Defaults.Add("controller", "Home")
route.Defaults.Add("action", "Index")

또는

[ "controller", "Home"
  "action", "Index" ]
|> List.iter route.Defaults.Add

F #에서는 익명 형식을 허용하는 오버로드 호출을 피할 것입니다. F #메서드를 호출하는 것을 피하기 때문입니다.FSharpListC #에서. 그것들은 언어 별 기능입니다. 대개 언어에 무관 한 과부하 / 해결 방법이 있습니다.

편집하다

문서를 보았습니다. 여기에 또 다른 방법이 있습니다.

let inline (=>) a b = a, box b

let defaults = dict [
  "controller" => "Home"
  "action"     => "Index" 
]
route.Defaults <- RouteValueDictionary(defaults)


  • +1 이것은 분명히 좋네요. 더 현명한 과부하가 있음을 알지 못했습니다.Add- 내 ASP.NET MVC 샘플에서도 사용해야합니다! - Tomas Petricek
  • Re : RouteValueDictionary를 사용합니다. 예상되는 사전 형식이 IDictionary < string, obj >이므로 컴파일되지는 않지만 작동하지 않습니다. 런타임에 " obj " 상자의 압축이 풀리므로 상자가 생성 될 때 먼저 박스에 표시해야합니다. 대신에, "dict [("controller ", box"Home "); ("action ", box"Index ")]"를 사용하십시오. 또한 혼합 된 유형의 기본값을 사용할 수 있습니다 (예 : ( "User", 박스 널), ( "id", 박스 UrlParameter.Optional). - Stephen Hosking
  • @ Javaman59 : 죄송합니다. 값을 입력하는 것을 잊어 버렸습니다. 결정된. 감사. - Daniel
  • @ 다니엘. 잘 했어. 나는 (= >) 연산자를 좋아한다. 훨씬 더 가독성있게 만듭니다. - Stephen Hosking

18

F #에서는 "익명 레코드"를 만들 수 없습니다. 유형을 사용할 때 익명이지만 레이블을 가지고 있지 않은 튜플을 사용하거나 사전에 선언하고 레이블이있는 레코드를 사용할 수 있습니다.

// Creating an anonymous tuple
let route = ("Home", "Index", UrlParameter.Optional)

// Declaration and creating of a record with named fields
type Route = { controller : string; action : string; id : UrlParameter } 
let route = { controller = "Home"; action = "Index"; id = UrlParameter.Optional } 

기술적으로 익명 레코드의 문제점은 실제 클래스로 정의되어야한다는 것입니다어딘가에(.NET 런타임에는 형식이 필요합니다.) 컴파일러가 모든 어셈블리에 넣으면 동일한 멤버가있는 두 개의 익명 레코드가 다른 어셈블리에 정의 된 경우 다른 형식이 될 수 있습니다.

솔직히, 나는 당신이 게시 한 예제가 ASP.NET에서의 잘못된 설계 결정 일 뿐이라고 생각합니다. 특정 C #기능을 사용하여 설계되지 않은 것을 수행하는 것은 오용입니다. 만큼 나쁘지 않을 수도 있습니다.,하지만 여전히 이상합니다. 라이브러리는 C #익명 형식을 취하지 만 사전으로 사용합니다. 즉, 지정해야하는 속성이 동적이기 때문에 키 - 값 쌍을 만드는 좋은 방법으로 라이브러리를 사용합니다.

따라서 F #에서 ASP.NET을 사용하는 경우 레코드를 만들지 않아도되는 대체 방법을 사용하는 것이 더 쉬울 것입니다. ASP.NET API가 일부 대안을 제공한다면 (다니엘이 보여 주듯이, 그것을 쓰는 방법).


  • @ 커크 : AnIDictionary더 나은 선택 같아. F #에서dict ["controller", "Home"; "action", "Index"]- 매우 자연 스럽습니다. - Daniel
  • 나는 그것이 실제로 간결하고 명확하지 않을 것이라고 생각한다.new Dictionary<string, object> { { "controller", "Home" }, { "action", "Index" } }new { controller = "Home", action = "Index" }(그리고 C #에서 더 나빠지는 해결책에 대해 구체적으로 묻고있었습니다) - Kirk Woll
  • 나는 말할 것도 없다.IDictionaryC #에서는 더 명확하거나 더 짧지 만 여러 언어가 CLR을 타깃으로한다는 점에서 더 나은 접근 방법입니다. 익명 형식은 C #에 고유합니다. - Daniel
  • 요컨대, ASP.NET이 .NET 라이브러리 (C #라이브러리가 아닌) 인 경우 사람들이 사용할 언어에 대한 가정을 간단히해서는 안됩니다. 사전을 표현하기 위해 속성이있는 클래스를 사용하면 순수한 .NET 관점에서 바보 같이 들립니다. - Tomas Petricek
  • @ Kirk - C #에서도 발견 가능성과 같은이 접근 방식에는 여전히 문제가 있습니다. 그만큼defaults매개 변수 유형 있음object" 기본 경로 값을 포함하는 개체 "라는 설명과 함께 호출자로서, 라이브러리에서 사용되는 심하게 관용적 인 스타일의 예제를 본 적이 없으면 완전히 이해하기 어렵습니다. 필자에게 이것은 F #에서 부족한 C #기능을 적극적으로 사용하기보다는 C #에서 간결한 컬렉션 리터럴을 지원할 수 없다는 문제를 해결하는 방법입니다. - kvb

11

OP는 익명 유형을 가장 잘 사용한다고 설명하지 않습니다. LINQ를 사용하여 임의의 클래스에 매핑 할 때 가장 잘 사용됩니다. 예 :

var results = context.Students
              .Where(x => x.CourseID = 12)
              .Select(x => new { 
                 StudentID = x.ID, 
                 Name = x.Forename + " " + x.Surname
              });

나는 이것이 새로운 레코드 유형을 정의함으로써 이루어질 수 있지만, 코드를 유지할 장소는 두 곳 (1) 레코드 유형 정의 (2)를 사용하여 할 수 있다는 것을 알고있다.

터플로 대신 할 수도 있지만 개별 필드에 액세스하려면 해체 구문을 사용해야합니다.(studentId, name)항상. 튜플에 5 개의 항목이 있다면 이것은 다루기 힘들어집니다. 나는 차라리 입력하고 싶다.x점을 찍고 인텔리 센스 (intellisense)를 통해 어떤 필드를 사용할 수 있는지 알려주십시오.


1

다음은 기본 웹 프로젝트 경로 설정에 대한 내용입니다.

module RouteConfig =

    open System.Web.Mvc
    open System.Web.Routing

    let registerRoutes (routes: RouteCollection) =

        routes.IgnoreRoute("{resource}.axd/{*pathInfo}")

        /// create a pair, boxing the second item
        let inline (=>) a b = a, box b

        /// set the Defaults property from a given dictionary
        let setDefaults defaultDict (route : Route) =  
            route.Defaults <- RouteValueDictionary(defaultDict)

        routes.MapRoute(name="Default", url="{controller}/{action}/{id}")
        |> setDefaults (dict ["controller" => "Home" 
                              "action" => "Index" 
                              "id" => UrlParameter.Optional])

연결된 질문


관련된 질문

최근 질문