2009-09-29 72 views
16

我想知道是否有任何允許命名元組的語言。即:具有不同類型和可配置名稱的多個變量的對象。允許命名元組的語言

例如爲:

public NamedTuple<double:Speed, int:Distance> CalculateStuff(int arg1, int arg2) 

var result = CalculateStuffTuple(1,2); 

Console.WriteLine("Speed is: " + result.Speed.ToString()) 
Console.WriteLine("Distance is: " + result.Distance.ToString()) 

我可以設想一個動態如何支持這樣的功能。我經常游泳的靜態語言(比如c#)可以做一個Dictionary,但這不是安全的,除非所有的項目都是相同的類型。或者你可以使用Tuple類型,但這意味着你有固定的成員名稱(Var1,Var2等)。

你也可以寫一個小的自定義類,但這是我想避免的情況。

我可以想象一個宏處理語言可以用靜態語言爲你編寫類似的東西,但我不知道這樣的語言。

這是從我的回答this question about return types

+0

我想避免一個自定義的類/結構的原因是,我不喜歡打字!沒有什麼更多。 – ligos 2009-09-30 03:06:37

+0

這行我應該不包括Tuple。 var result = CalculateStuffTuple(1,2); – 2012-02-03 11:49:38

回答

18

在C#中,您有匿名類型;這些都是相似的,但有其自身的侷限性:

var result = new { Speed = 12.4, Distance = 8, Caption = "car 1" }; 

然而,這是很難消費這些作爲呼叫者,除非你用「舉例投」(脆),反射或dynamic。其中最後一個是最令人開胃的。

dynamic result = GetSomething(); 
Console.WriteLine(result.Speed); 
Console.WriteLine(result.Distance); 

在大多數情況下,使用常規類會更好 - 但這種方法確實有一些實際用途;例如,看看他們如何在ASP中使用。NET MVC簡單而方便地傳遞配置信息(否則需要字典)。有點像jQuery如何讓選項作爲屬性傳遞給對象。

+0

這似乎是最接近我所要求的(至少在C#中)。 – ligos 2009-09-30 03:03:41

-1

我不確定你會需要什麼 - 一個元組只是一個結構,持有不同類型的數據。如果你真的想要命名的屬性,你將不得不創建一個自定義類型或動態創建一個匿名類型。

我不知道任何靜態類型的語言,可以支持這個,但C#肯定沒有。

3

你是說,像Python的collections.namedtuple?那麼,Python(當前版本,2.6和3.1)支持他們;-)。但嚴重的是,我不知道一個靜態類型的語言將它們作爲內置的語言。

2

在C#中使用結構或類有什麼問題?

public class SpeedDistance{ 
    public double Speed; 
    public int Distance; 
} 
+2

那麼,公共領域當然是一個壞主意......但是'public double Speed {get; set;}'會做; -p – 2009-09-29 04:30:13

+1

我喜歡我的元組是不可變的。這需要只讀變量,而不是一個構造函數,它開始變得太長。 – ligos 2009-09-30 03:05:07

+1

公共領域是可以的,當且僅當所有類都包含。但是元組也可以有很多其他好的屬性,這些屬性在傳遞給其他庫時會有所幫助。如果它們每次都是從頭開始編寫的,那麼它們就不會互操作。 – 2012-02-03 12:05:07

3

我不知道,如果這是你在尋找什麼,但在Haskell,你可以有特定名稱和類型的記錄:

data Movement = Movement { speed :: Double, distance :: Int } deriving (Show) 

main = do 
    print $ Movement 3.14 100 
    print Movement {distance = 5, speed = 2.1} 
    print Movement {speed = 9, distance = -4} 

輸出:

 
Movement {speed = 3.14, distance = 100} 
Movement {speed = 2.1, distance = 5} 
Movement {speed = 9.0, distance = -4} 

但它在技術上不是元組。 Haskell 確實有有元組,但據我所知它們不具名稱。

這真的離任何C語言的簡單結構都不遠。也許我錯過了一些問題。

6

埃菲爾允許命名元組。

5

我知道;

  • 的Python(動態,強類型)
  • 艾菲爾(靜態,字符串類型)

既可以在.NET

使用

,可能Lisp中,你可以用Lisp的做任何事。

39

老問題,但需要一個更好的解決方案,我認爲的。

你可以得到一個名爲採取的元組類型的優勢,但在一個包裝.Item1,.Item2等有意義的屬性名稱自定義命名類型包裹它的參數。

我太討厭這樣一個事實,即元組具有未命名的參數,使代碼無法讀取,但不能忽略它自己節省的時間,無法自行實現IComparable,IStructuralEquatable等,以便您可以安全地將結構用作字典關鍵,例如。

我覺得這是一個非常愉快的妥協:

public class Velocity : Tuple<double, double, string> 
{ 
    public Velocity(double Speed, double Direction, string Units) : base(Speed, Direction, Units) { } 
    public double Speed { get { return this.Item1; } } 
    public double Direction { get { return this.Item2; } } 
    public string Units { get { return this.Item3; } } 
} 

現在不是這種垃圾:

Tuple<double, double, string> myVelocity = new Tuple<double, double, string>(10, 2.34, "cm/s"); 
System.Diagnostics.Debug.Print("Speed: " + myVelocity.Item1); 
System.Diagnostics.Debug.Print("Direction: " + myVelocity.Item2); 
System.Diagnostics.Debug.Print("Units: " + myVelocity.Item3); 

你得到這樣做:

Velocity myVelocity2 = new Velocity(10, 2.34, "cm/s"); 
System.Diagnostics.Debug.Print("Speed: " + myVelocity2.Speed); 
System.Diagnostics.Debug.Print("Direction: " + myVelocity2.Direction); 
System.Diagnostics.Debug.Print("Units: " + myVelocity2.Units); 

而且你還受益從所有美妙的元組功能,讓你用它作爲一個複雜的密鑰在字典等

唯一的缺點是,如果你只使用單一方法的範圍內,本計劃的元組,您必須聲明,方法中包含類的範圍內的類型。對於大多數應用程序,我不認爲這是一個問題。

+0

這其實並不算太壞。除了我必須有一堆圍繞'Tuple <>'包裝的小類。但它不得不重新實現IEquatable,IComparable等。 – ligos 2012-08-08 23:47:00

+1

我不敢相信我從來沒有想到這一點。超級有用。 – 2014-03-24 22:45:37

+0

只是我正在尋找的解決方案。偉大的:) – 2015-03-04 11:02:46

0

謝謝Alain。以下是我如何使用您的提示。對於轉盤

<div id="owl" class="owl-carousel owl-theme"> 
    @foreach (var image in Model.Sketches) 
    { 
     <div class="item" > 
      <a href="@image.SketchHref" id="[email protected]" target="_blank" > 
       <img id="[email protected]" class="lazyOwl" style="border:1px solid #d1c7c7;outline : 0;max-height:350px;max-width:400px;" 
        title="click for full size" alt="@image.SketchName" data-src="@image.SketchHref" /></a> 
        <div style="text-align:left;height:auto;vertical-align:bottom;padding:2px;font-size:1em;color:#DF3A01;">Sketch @image.SketchNumber of @Model.Sketches.Count()</div> 
     </div> 
    } 
    </div> 

而對於C#

public List<Sketches> Sketches 
    { 
     get 
     { 
      List<Sketches> hrefs = new List<Sketches>(); 

/* 圖像名稱

動態圖像加載器相匹配的文件夾位置 例如:1234101005_001。GIF就等於 「C:\影像\ 1234 \ 10 \ 1005_BLD \」 */

  var sketchFolder = Regex.Replace(some_image, @"(\d{4})(\d{2})(\d{4})", @"c:\Sketches\$1\$2\$3\_BLD"); 
      var sketchHref = Regex.Replace(some_image, @"(\d{4})(\d{2})(\d{4})", @"/sketches/$1/$2/$3/_BLD"); 
      Int16 i = 0; 

      if (System.IO.Directory.Exists(sketchFolder)) 
      { 
       List<string> gifs = GetGifs(sketchFolder); 

       gifs.ForEach(delegate(String gif) 
       { 
        string s = sketchHref + "/" + gif; 
        string f = sketchFolder + "/" + gif; 

        if (System.IO.File.Exists(f)) 
        { 
         Sketches sketch = new Sketches(s, (++i).ToString(), gif); 
         hrefs.Add(sketch); 
        } 
        else // gif does not exist 
        { 
         Sketches sketch = new Sketches("placeholder.png", (++i).ToString(), gif); 
         hrefs.Add(sketch); 
        } 
       }); 
      } 
      else // folder does not exist 
      { 
       Sketches sketch = new Sketches("placeholder.png", (++i).ToString(), ""); 
       hrefs.Add(sketch); 
      } 
      return hrefs; 
     } 
    } 

public class Sketches : Tuple<string, string, string> 
{ 
    public Sketches(string SketchHref, string SketchNumber, string SketchName) : base(SketchHref, SketchNumber, SketchName) { } 
    public string SketchHref { get { return this.Item1; } } 
    public string SketchNumber { get { return this.Item2; } } 
    public string SketchName { get { return this.Item3; } } 
} 
1

斯威夫特允許命名元組。你可以寫如下:

let interval = (start: 0, end: 10) 
let start = interval.start 

它們實際上是匿名結構。