Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/263.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# F#中的名称元组/匿名类型?_C#_F# - Fatal编程技术网

C# F#中的名称元组/匿名类型?

C# F#中的名称元组/匿名类型?,c#,f#,C#,F#,在C#中,您可以执行以下操作: var a=new{name=“cow”,sound=“mooo”,omg=“wtfbbq”}; 在Python中,您可以执行以下操作 a=t(name=“cow”,sound=“mooo”,omg=“wtfbbq”) 当然,默认情况下不是这样,但是实现一个类t可以让您这样做,这很简单。事实上,当我在使用Python时,我确实做到了这一点,并且发现它对于小型一次性容器非常方便,您希望能够通过名称而不是索引(很容易混淆)访问组件 除此之外,它们基本上与它们所服务

在C#中,您可以执行以下操作:

var a=new{name=“cow”,sound=“mooo”,omg=“wtfbbq”};
在Python中,您可以执行以下操作

a=t(name=“cow”,sound=“mooo”,omg=“wtfbbq”)
当然,默认情况下不是这样,但是实现一个类
t
可以让您这样做,这很简单。事实上,当我在使用Python时,我确实做到了这一点,并且发现它对于小型一次性容器非常方便,您希望能够通过名称而不是索引(很容易混淆)访问组件

除此之外,它们基本上与它们所服务的生态位中的元组相同

特别是,我现在正在研究这个C代码:

routes.MapRoute(
“默认值”,//路由名称
“{controller}/{action}/{id}”,//带参数的URL
新建{controller=“Home”,action=“Index”,id=UrlParameter.Optional}//参数默认值
);
它是F#等价物

类型路由={
控制器:字符串
动作:字符串
id:UrlParameter}
routes.MapRoute(
“默认值”,//路由名称
“{controller}/{action}/{id}”,//带参数的URL
{controller=“Home”action=“Index”id=UrlParameter.Optional}//参数默认值
)
这既冗长又重复,更不用说相当烦人了。在F#中,你能接近这种语法吗?我不介意现在跳过一些障碍(甚至是燃烧的障碍!),如果这意味着它会给我一些有用的东西来干涸这样的代码。

我发现这样做更容易

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

在F#中,我将避免调用接受匿名类型的重载,就像我将避免调用从C#接受
FSharpList
的F#方法一样。这些是特定于语言的特性。通常有一种语言不可知的过载/解决方法可用

编辑 看看这些文件,这里还有另一种方法

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

let defaults = dict [
  "controller" => "Home"
  "action"     => "Index" 
]
route.Defaults <- RouteValueDictionary(defaults)
让内联(=>)a b=a,框b
让默认值=dict[
“控制器”=>“主”
“操作”=>“索引”
]
route.Defaults不能在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提供了一些替代方法(如Daniel所示,有一种更好的编写方法)。

以下是我对默认web项目路由配置的看法:

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])
模块路由图=
opensystem.Web.Mvc
open System.Web.Routing
let registerOutes(路由:RouteCollection)=
routes.IgnoreRoute(“{resource}.axd/{*pathInfo}”)
///创建一对,装箱第二项
让内联(=>)a b=a,框b
///设置给定字典中的Defaults属性
让SetDefaultDefaultDict(路由:路由)=
路由默认设置默认值(dict[“控制器”=>“主”
“操作”=>“索引”
“id”=>UrlParameter.Optional])

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告诉我哪些字段可用。

现在在F#4.6(预览版)中,我们有了

因此,我们可以使用以下代码语法:

let AwesomeAnonymous = {|  ID = Guid.NewGuid()
                           Name = "F#"
                        |}

AwesomeAnonymous.Name |> Debug.WriteLine
Visual Studio Intellisense也支持它:

所以代码可以是这样的:

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

另请参见:

正如Tony在回答中所指出的,这与F#4.6相比并没有太大的改善。使用.NET Core SDK 3.0.100-preview4-011158测试类似示例,我能够演示新功能的使用。至于
RouteMap
方法,我不知道该API接受哪种类型的值,但我怀疑下面的示例会起作用

请注意,在花括号的内侧使用了
|
字符。这就是F#中常规记录与匿名记录的区别

至于你的另一个例子,也许F#的例子现在看起来是这样的

let a = {| name = "cow"; sound = "moooo"; omg = "wtfbbq" |}

只需提到匿名类型在c中不是元组,有元组类ESF#4.6预览:匿名记录+1这绝对更好。我不知道有一个更合理的重载用于
Add
——我也应该在我的ASP.NET MVC示例中使用它!回复:使用RouteValueDictionary。这可以编译,但不起作用,因为预期的字典类型是IDictionary。在运行时,它会取消对“obj”的装箱,因此在创建它时必须首先将其装箱。而是使用:“dict[(“controller”,box“Home”);(“action”,box“Index”)]”。这也会启用混合类型的默认值
routes.MapRoute(
    "Default", // Route name
    "{controller}/{action}/{id}", // URL with parameters
    {| controller = "Home"; action = "Index"; id = UrlParameter.Optional |} // Parameter defaults
  )
let a = {| name = "cow"; sound = "moooo"; omg = "wtfbbq" |}