โครงสร้างข้อมูลสำหรับการเข้าถึงหน่วยวัด


17

TL; DR - ฉันพยายามออกแบบโครงสร้างข้อมูลที่ดีที่สุดเพื่อกำหนดหน่วยภายในหน่วยการวัด


Unit of measureเป็นหลักvalue(หรือปริมาณ) unitที่เกี่ยวข้องกับ หน่วย SIมีเจ็ดฐานหรือขนาด กล่าวคือความยาวมวลเวลากระแสไฟฟ้าอุณหภูมิปริมาณสาร (โมล) และความเข้มการส่องสว่าง

สิ่งนี้จะตรงไปตรงมามากพอ แต่มีหน่วยที่ได้รับมาจำนวนมากรวมทั้งอัตราที่เราใช้บ่อย ตัวอย่างรวมหน่วยจะเป็นนิวตัน: และอัตราตัวอย่างจะเป็นkg * m / s^2tons / hr

เรามีแอปพลิเคชั่นที่ต้องอาศัยหน่วยงานโดยนัย เราจะฝังหน่วยภายในชื่อตัวแปรหรือคอลัมน์ แต่สิ่งนี้จะสร้างปัญหาเมื่อเราจำเป็นต้องระบุหน่วยการวัดด้วยหน่วยที่แตกต่างกัน ใช่เราสามารถแปลงค่าที่อินพุทและจอแสดงผล แต่สิ่งนี้จะสร้างรหัสค่าใช้จ่ายจำนวนมากที่เราต้องการห่อหุ้มในคลาสของตัวเอง

มีโซลูชั่นจำนวนมากเกี่ยวกับ codeplex และสภาพแวดล้อมการทำงานร่วมกันอื่น ๆ การอนุญาตให้ใช้สิทธิ์สำหรับโครงการนั้นเป็นที่ยอมรับ แต่โดยทั่วไปแล้วโครงการมักจะมีน้ำหนักเบาหรือหนักเกินไป เรากำลังไล่ตามยูนิคอร์นของเรา "ถูกต้อง"

เป็นการดีที่ฉันสามารถกำหนดหน่วยวัดใหม่โดยใช้สิ่งนี้:

UOM myUom1 = UOM ใหม่ (10, โวลต์);
UOM myUom2 = UOM ใหม่ (43.2, Newtons);

แน่นอนว่าเราใช้การผสมผสานระหว่างหน่วย Imperial และ SI ตามความต้องการของลูกค้า

นอกจากนี้เรายังต้องรักษาโครงสร้างหน่วยของข้อมูลให้ตรงกันกับตารางฐานข้อมูลในอนาคตเพื่อให้เราสามารถให้ข้อมูลที่สอดคล้องกันในระดับเดียวกัน


อะไรคือวิธีที่ดีที่สุดในการกำหนดหน่วยหน่วยที่ได้รับและอัตราที่เราต้องใช้เพื่อสร้างหน่วยวัดระดับของเรา ฉันเห็นการใช้ enums ตั้งแต่หนึ่งตัวขึ้นไป แต่อาจทำให้ผู้พัฒนารายอื่นผิดหวังได้ enum เดียวจะมีขนาดใหญ่กว่า 200+ รายการในขณะที่หลาย enums อาจสร้างความสับสนโดยยึดตามหน่วย SI เทียบกับ Imperial และรายละเอียดเพิ่มเติมตามหมวดหมู่ของหน่วยเอง

ตัวอย่าง Enum แสดงข้อกังวลของฉัน:

myUnits.Volt
myUnits.Newton
myUnits.meter

SIUnit.meter
ImpUnit.foot DrvdUnit.Newton
DrvdUnitSI.Newton
DrvdUnitImp.FtLbs

ชุดของหน่วยที่ใช้งานของเรานั้นค่อนข้างชัดเจนและเป็นพื้นที่ จำกัด เราต้องการความสามารถในการขยายและเพิ่มหน่วยที่ได้รับใหม่หรืออัตราเมื่อเรามีความต้องการของลูกค้าสำหรับพวกเขา โครงการอยู่ใน C # ถึงแม้ว่าฉันคิดว่าการออกแบบที่กว้างขึ้นสามารถใช้ได้กับหลายภาษา


หนึ่งในห้องสมุดที่ฉันดูช่วยให้สามารถป้อนหน่วยอิสระผ่านสายอักขระได้ จากนั้นคลาส UOM ของพวกเขาจะวิเคราะห์สตริงและ slotted สิ่งต่าง ๆ ตามลำดับ ความท้าทายด้วยวิธีนี้คือมันบังคับให้นักพัฒนาคิดและจดจำรูปแบบสตริงที่ถูกต้อง และฉันเสี่ยงต่อข้อผิดพลาด / ข้อยกเว้นรันไทม์หากเราไม่เพิ่มการตรวจสอบเพิ่มเติมภายในรหัสเพื่อตรวจสอบความถูกต้องของสตริงที่ส่งผ่านในตัวสร้าง

อีกไลบรารีหนึ่งสร้างคลาสมากเกินไปที่ผู้พัฒนาจะต้องทำงานด้วย พร้อมกับ UOM เทียบเท่ามันให้DerivedUnitและRateUnitและอื่น ๆ โดยพื้นฐานแล้วรหัสนั้นซับซ้อนเกินไปสำหรับปัญหาที่เรากำลังแก้ไข ไลบรารี่นั้นอนุญาตให้มีอะไรก็ได้: ชุดค่าผสมใด ๆ (ซึ่งถูกต้องตามกฎหมายในโลกหน่วย) แต่เรายินดีที่จะกำหนดขอบเขตปัญหาของเรา (ทำให้รหัสของเราง่ายขึ้น) โดยไม่อนุญาตให้ใช้ชุดค่าผสมที่เป็นไปได้ทั้งหมด

ห้องสมุดอื่น ๆ เรียบง่ายอย่างน่าขันและไม่เคยแม้แต่จะถือว่าผู้ให้บริการโหลดมากเกินไป

นอกจากนี้ฉันไม่กังวลเกี่ยวกับความพยายามในการแปลงที่ไม่ถูกต้อง (ตัวอย่างเช่น: โวลต์เป็นเมตร) ผู้พัฒนาเป็นคนเดียวที่จะเข้าถึงได้ในระดับนี้ ณ จุดนี้และเราไม่จำเป็นต้องป้องกันความผิดพลาดเหล่านั้น


คุณสามารถอธิบายด้วยวิธีการใดว่าห้องสมุดที่คุณพบนั้นไม่ตรงกับความต้องการของคุณ?
svick

1
ดูเพิ่มเติมstackoverflow.com/q/348853/240613
Arseni Mourzenko

1
@MainMa - ขอบคุณสำหรับลิงค์นั้น เราไม่จำเป็นต้องทำการวิเคราะห์เชิงมิติเนื่องจากพื้นที่ปัญหาของเรามีขนาดเล็กพอที่จะประกาศการแปลงที่อนุญาต มันจะเป็นคำขวัญในการสร้าง แต่นั่นเป็นค่าใช้จ่ายครั้งเดียว

1
คุณอธิบายได้ไหมว่าคุณต้องการแปลงแบบไหน มันเป็นเพียงการปรับขนาดการแปลง (เช่นเมตรเป็นเซนติเมตร) หรือการแปลงข้ามมิติ (เช่นมวลเพื่อบังคับ)
Bart van Ingen Schenau

1
คุณคิดว่าจะย้ายส่วนของรหัสไปที่ F # หรือไม่? ภาษานั้นมีหน่วยของการวัดการสร้าง int
Pete

คำตอบ:


11

Boost ห้องสมุดสำหรับ C ++ รวมถึงบทความเกี่ยวกับการวิเคราะห์มิติที่นำเสนอตัวอย่างการใช้งานของการจัดการหน่วยวัด

เพื่อสรุป: หน่วยการวัดจะแสดงเป็นเวกเตอร์โดยแต่ละองค์ประกอบของเวกเตอร์แสดงถึงมิติพื้นฐาน:

typedef int dimension[7]; // m  l  t  ...
dimension const mass      = {1, 0, 0, 0, 0, 0, 0};
dimension const length    = {0, 1, 0, 0, 0, 0, 0};
dimension const time      = {0, 0, 1, 0, 0, 0, 0};

หน่วยที่ได้มาคือการรวมกันของสิ่งเหล่านี้ ตัวอย่างเช่นแรง (มวล * ระยะทาง / เวลา ^ 2) จะถูกแทนด้วย

dimension const force  = {1, 1, -2, 0, 0, 0, 0};

หน่วย Imperial กับ SI สามารถจัดการได้โดยการเพิ่มปัจจัยการแปลง

การใช้งานนี้อาศัยเทคนิคเฉพาะ C ++ (โดยใช้เทมเพลต metaprogramming เพื่อเปลี่ยนหน่วยการวัดที่แตกต่างกันให้เป็นประเภทเวลาคอมไพล์ที่แตกต่างกันได้ง่าย) แต่แนวคิดนี้ควรถ่ายโอนไปยังภาษาการเขียนโปรแกรมอื่น ๆ


ดังนั้นหน่วยที่ได้รับทั้งหมดจะเท่ากับ C ++ consts? ฉันคิดว่ามันถูกห่อไว้ในเนมสเปซเพื่อหลีกเลี่ยงสิ่งสกปรกหรือไม่

1
@ GlenH7 - สิ่งนี้เข้าสู่สิ่งที่เทมเพลต metaprogramming จริงๆแล้วพวกมันจะถูกแยกประเภท (เช่น, mpl::vector_c<int,1,0,0,0,0,0,0>) แทนที่จะเป็น const; บทความนำเสนอแนวทาง consts เป็นครั้งแรกโดยวิธีการอธิบาย (และฉันอาจไม่ได้อธิบายอย่างนั้น) การใช้ const จะใช้เป็นทางเลือก (คุณอาจสูญเสียความปลอดภัยประเภทเวลาในการคอมไพล์) การใช้เนมสเปซเพื่อหลีกเลี่ยงมลภาวะของชื่อเป็นตัวเลือกอย่างแน่นอน
Josh Kelley

8

ฉันเพียงแค่เปิดตัว Units.NET บนGithubและNuGet

มันให้หน่วยทั่วไปและการแปลงทั้งหมดแก่คุณ มันมีน้ำหนักเบาหน่วยทดสอบและรองรับ PCL

ต่อคำถามของคุณ:

  • นี่คือจุดสิ้นสุดของการใช้งานที่เบากว่า โฟกัสคือการช่วยในการเป็นตัวแทนการแปลงและการสร้างหน่วยวัด
  • ไม่มีตัวแก้สมการมันไม่ได้รับหน่วยใหม่โดยอัตโนมัติจากการคำนวณ
  • หนึ่ง enum ใหญ่สำหรับการกำหนดหน่วย
  • คลาส UnitConverter สำหรับการแปลงระหว่างหน่วยแบบไดนามิก
  • โครงสร้างข้อมูลที่ไม่เปลี่ยนรูปสำหรับการแปลงอย่างชัดเจนระหว่างหน่วย
  • ตัวดำเนินการโอเวอร์โหลดสำหรับเลขคณิตอย่างง่าย
  • การขยายไปยังหน่วยและการแปลงใหม่เป็นเรื่องของการเพิ่ม enum ใหม่สำหรับการแปลงแบบไดนามิกและการเพิ่มหน่วยของระดับการวัดเช่นความยาวเพื่อกำหนดคุณสมบัติการแปลงที่ชัดเจนและการโอเวอร์โหลดของผู้ปฏิบัติงาน

ฉันยังไม่ได้เห็นจอกศักดิ์สิทธิ์ของการแก้ปัญหาในโดเมนนี้ ในขณะที่คุณระบุมันสามารถกลายเป็นวิธีที่ซับซ้อนเกินไปหรือ verbose เกินไปที่จะทำงานกับ บางครั้งมันเป็นการดีที่สุดที่จะทำให้สิ่งต่าง ๆ เรียบง่ายและสำหรับความต้องการของฉันวิธีการนี้ได้รับการพิสูจน์แล้วว่าเพียงพอ

การแปลงที่ชัดเจน

Length meter = Length.FromMeters(1);
double cm = meter.Centimeters; // 100
double yards = meter.Yards; // 1.09361
double feet = meter.Feet; // 3.28084
double inches = meter.Inches; // 39.3701

Pressure p = Pressure.FromPascal(1);
double kpa = p.KiloPascals; // 1000
double bar = p.Bars; // 1 × 10-5
double atm = p.Atmosphere; // 9.86923267 × 10-6
double psi = p.Psi; // 1.45037738 × 10-4

การแปลงแบบไดนามิก

// Explicitly
double m = UnitConverter.Convert(1, Unit.Kilometer, Unit.Meter); // 1000
double mi = UnitConverter.Convert(1, Unit.Kilometer, Unit.Mile); // 0.621371
double yds = UnitConverter.Convert(1, Unit.Meter, Unit.Yard); // 1.09361

// Or implicitly.
UnitValue val = GetUnknownValueAndUnit();

// Returns false if conversion was not possible.
double cm;
val.TryConvert(LengthUnit.Centimeter, out cm);

ตัวอย่างของคุณดูเหมือนจะใช้ aTruple<T1, T2, T3>(x, y, z)
Chef_Code

ไม่แน่ใจว่าคุณหมายถึงอะไรมีค่าเพียงค่าเดียวสำหรับแต่ละหน่วย สำหรับความยาวมันจะเก็บฟิลด์เป็นเมตรชนิดที่สองและสำหรับมวลนั้นจะเป็นกิโลกรัม เมื่อแปลงเป็นหน่วยอื่นมันจะเรียกใช้ค่านั้นผ่านฟังก์ชั่นการแปลง ตัวอย่างเหล่านี้ล้าสมัยไปเล็กน้อยในขณะนี้ แต่ใช้แนวคิดเดียวกันนี้
angularsen

ผมคิดว่าผม misspoke เช่นเดียวกับการเพิ่มขึ้นถึงข้อสรุป ... Tupleผมหมายถึง ฉันไม่เห็นUnitConverterชั้นเรียนของคุณแต่ IMO ดูเหมือนว่ามันอาจมีฟังก์ชั่นที่คล้ายกันในTupleชั้นเรียน
Chef_Code

ยังไม่แน่ใจเกี่ยวกับการเปรียบเทียบ Tuple แต่ดูหน้า Githubเพื่อดูตัวอย่างการใช้งานที่อัปเดต
angularsen

3

หากคุณสามารถดึงการเปลี่ยนเป็น F # โดยใช้ C # ได้ F # จะมีหน่วยของระบบการวัด (นำมาใช้โดยใช้ข้อมูลเมตาของค่า) ที่ดูเหมือนว่ามันจะพอดีกับสิ่งที่คุณกำลังพยายามทำ:

http://en.wikibooks.org/wiki/F_Sharp_Programming/Units_of_Measure

สะดุดตา:

// Additionally, we can define types measures which are derived from existing measures as well:

[<Measure>] type m                  (* meter *)
[<Measure>] type s                  (* second *)
[<Measure>] type kg                 (* kilogram *)
[<Measure>] type N = (kg * m)/(s^2) (* Newtons *)
[<Measure>] type Pa = N/(m^2)       (* Pascals *)

คำแนะนำที่ดีและเราได้พิจารณาแล้ว ฉันไม่เชื่อว่า F # ให้ความสามารถแก่เราในการควบคุมวิธีที่หน่วยท้ายที่สุดจะปรากฏในเอาต์พุตแม้ว่า

2
@ GlenH7 ฉันเชื่อว่าคุณพูดถูก:Important: Units of measure look like a data type, but they aren't. .NET's type system does not support the behaviors that units of measure have, such as being able to square, divide, or raise datatypes to powers. This functionality is provided by the F# static type checker at compile time, **but units are erased from compiled code**. Consequently, it is not possible to determine value's unit at runtime.
พอล

3

จากความจริงที่ว่าการแปลงที่ต้องการทั้งหมดเป็นการปรับขนาดการแปลง (ยกเว้นถ้าคุณต้องรองรับการแปลงอุณหภูมิการคำนวณที่การแปลงเกี่ยวข้องกับการชดเชยมีความซับซ้อนมากขึ้น) ฉันจะออกแบบระบบ 'หน่วยการวัด' ของฉันดังนี้:

  • คลาสunitที่มีตัวคูณสเกล, สตริงสำหรับการแสดงข้อความของหน่วยและการอ้างอิงที่unitสเกลถึง การแสดงข้อความต้นฉบับนั้นมีไว้เพื่อจุดประสงค์ในการแสดงผลและการอ้างอิงไปยังหน่วยพื้นฐานเพื่อให้ทราบว่าหน่วยผลลัพธ์นั้นเกิดขึ้นเมื่อทำการคำนวณทางคณิตศาสตร์กับค่าที่มีหน่วยต่าง

    สำหรับแต่ละหน่วยที่ได้รับการสนับสนุนunitจะมีการจัดเตรียมอินสแตนซ์ของคลาส

  • ชั้นที่มีคุณค่าและการอ้างอิงไปยังค่าUOM ระดับให้ผู้ประกอบการมากเกินไปสำหรับการเพิ่ม / ลบอีกunitUOMUOMและคูณ / หารด้วยค่ามิติ

    หากทำการบวก / ลบในสองUOMสิ่งเดียวกันunitมันจะถูกดำเนินการโดยตรง มิฉะนั้นค่าทั้งสองจะถูกแปลงเป็นหน่วยพื้นฐานที่เกี่ยวข้องและบวก / ลบ unitผลที่ตามมามีรายงานว่าอยู่ในฐาน

การใช้งานจะเป็นอย่างไร

unit volts = new unit(1, "V"); // base-unit is self
unit Newtons = new unit(1, "N"); // base-unit is self
unit kiloNewtons = new unit(1000, "kN", Newtons);
//...
UOM myUom1 = new UOM(10, volts);
UOM myUom2 = new UOM(43.2, kiloNewtons);

เนื่องจากการดำเนินการในหน่วยที่เข้ากันไม่ได้จะไม่ถือว่าเป็นปัญหาฉันจึงไม่ได้พยายามทำให้ประเภทการออกแบบปลอดภัยในส่วนนั้น เป็นไปได้ที่จะเพิ่มการตรวจสอบรันไทม์โดยการตรวจสอบว่าสองหน่วยอ้างอิงถึงหน่วยฐานเดียวกัน


เมื่อคุณพูดถึงอุณหภูมิ: อะไรนะ95F - 85F? คือ20C - 15Cอะไร ในตัวอย่างทั้งสองทั้งUOMs unitจะมีเหมือนกัน การลบจะดำเนินการโดยตรงหรือไม่

@MattFenwick: ผลจะเป็นตามลำดับและ10 F 5 Cการคำนวณจะดำเนินการโดยตรงถ้าเป็นไปได้เพื่อหลีกเลี่ยงการแปลงที่ไม่จำเป็น มันจะค่อนข้างง่ายที่จะเพิ่มวิธีการแปลงหน่วยUOMแต่สำหรับการแปลงเซลเซียส - ฟาเรนไฮต์unitชั้นจะต้องมีการขยายความเป็นไปได้ของการชดเชยนอกเหนือจากปัจจัยการปรับขนาด
Bart van Ingen Schenau

แต่95F - 85F! 10F=

1
@ MattFenwick: โปรดให้ความกระจ่างแก่ฉัน มันจะเย็นแค่ไหนถ้าคุณลดอุณหภูมิ95Fลง85F? สำหรับความรู้ของฉันฟาเรนไฮต์ยังคงเป็นขนาดเชิงเส้น
Bart van Ingen Schenau

2
ลองทำตัวอย่างเซลเซียสเพราะมันง่ายกว่าที่จะแปลงเป็นเคลวิน: ถ้าเราพูด20C - 15C = 5Cแล้วเรากำลังพูด293.15K - 288.15K = 278.15Kซึ่งผิดอย่างชัดเจน

2

ลองคิดดูว่าโค้ดของคุณกำลังทำอะไรอยู่ การมีการแจงนับง่าย ๆ กับหน่วยที่เป็นไปได้ทั้งหมดช่วยให้ฉันทำบางอย่างเช่นแปลงโวลต์เป็นเมตร เห็นได้ชัดว่าไม่ถูกต้องกับมนุษย์ แต่ซอฟต์แวร์ยินดีที่จะลอง

ผมทำอะไรรางที่คล้ายกันครั้งนี้และการดำเนินงานของฉันมีฐานเรียนนามธรรม (ความยาว, น้ำหนัก, ฯลฯ ) IUnitOfMeasureที่ดำเนินการทั้งหมด แต่ละระดับฐานนามธรรมกำหนดประเภทเริ่มต้น (ชั้นLengthมีการใช้งานเริ่มต้นของชั้นเรียนMeter) ว่ามันจะใช้สำหรับงานการแปลงทั้งหมด ดังนั้นIUnitOfMeasureการดำเนินการทั้งสองวิธีที่แตกต่างกันและToDefault(decimal)FromDefault(decimal)

จำนวนจริงที่ฉันต้องการตัดคือประเภททั่วไปที่ยอมรับIUnitOfMeasureว่าเป็นอาร์กิวเมนต์ทั่วไป การพูดอะไรทำนองMeasurement<Meter>(2.0)นี้จะทำให้คุณปลอดภัยโดยอัตโนมัติ การใช้การแปลงโดยนัยและวิธีการทางคณิตศาสตร์ที่เหมาะสมในชั้นเรียนเหล่านี้ช่วยให้คุณทำสิ่งต่าง ๆ เช่นMeasurement<Meter>(2.0) * Measurement<Inch>(12)และส่งคืนผลลัพธ์ในประเภทเริ่มต้น ( Meter) ฉันไม่เคยทำงานออกหน่วยที่ได้รับเช่นนิวตัน; ฉันปล่อยให้พวกเขาเป็นกิโลกรัม * เมตร / วินาที / วินาที


ฉันชอบวิธีที่คุณแนะนำด้วยการใช้งานประเภททั่วไป

1

ฉันเชื่อว่าคำตอบอยู่ในการตอบสนอง Stack Overflow ของ MarioVWไปที่:

ตัวอย่างการปฏิบัติที่ Tuple สามารถใช้ได้ใน. Net 4-0

ด้วย tuples คุณสามารถใช้พจนานุกรมสองมิติได้อย่างง่ายดาย (หรือ n-dimension สำหรับเรื่องนั้น) ตัวอย่างเช่นคุณสามารถใช้พจนานุกรมดังกล่าวเพื่อใช้การจับคู่การแลกเปลี่ยนสกุลเงิน:

var forex = new Dictionary<Tuple<string, string>, decimal>();
forex.Add(Tuple.Create("USD", "EUR"), 0.74850m); // 1 USD = 0.74850 EUR
forex.Add(Tuple.Create("USD", "GBP"), 0.64128m);
forex.Add(Tuple.Create("EUR", "USD"), 1.33635m);
forex.Add(Tuple.Create("EUR", "GBP"), 0.85677m);
forex.Add(Tuple.Create("GBP", "USD"), 1.55938m);
forex.Add(Tuple.Create("GBP", "EUR"), 1.16717m);
forex.Add(Tuple.Create("USD", "USD"), 1.00000m);
forex.Add(Tuple.Create("EUR", "EUR"), 1.00000m);
forex.Add(Tuple.Create("GBP", "GBP"), 1.00000m);
decimal result;
result = 35.0m * forex[Tuple.Create("USD", "EUR")]; // USD 35.00 = EUR 26.20
result = 35.0m * forex[Tuple.Create("EUR", "GBP")]; // EUR 35.00 = GBP 29.99
result = 35.0m * forex[Tuple.Create("GBP", "USD")]; // GBP 35.00 = USD 54.58

ฉันมีความต้องการคล้ายกันสำหรับใบสมัครของฉัน Tupleก็ไม่เปลี่ยนรูปซึ่งก็เป็นจริงของวัตถุเช่นน้ำหนักและมาตรการ ... เมื่อพูดไป "โลกรอบตัวปอนด์"


0

รหัสต้นแบบของฉัน: http://ideone.com/x7hz7i

คะแนนการออกแบบของฉัน:

  1. ตัวเลือกของ UoM (หน่วยวัด) เป็นคุณสมบัติ / ชุด
    ความยาว len = ใหม่ความยาว ();
    len.Meters = 2.0;
    Console.WriteLine (len.Feet);
    
  2. นวกรรมิกที่มีชื่อสำหรับตัวเลือกของหนี้
    ความยาว len = ความยาวจากมิเตอร์ (2.0);
    
  3. ToString รองรับ UoM
    Console.WriteLine (len.ToString ( "ฟุต"));
    Console.WriteLine (len.ToString ( "F15"));
    Console.WriteLine (len.ToString ( "ftF15"));
    
  4. การแปลงไปกลับ
    ความยาว lenRT = ความยาวจากเครื่องวัดความยาว (ความยาวจากหน้าจอ (ความยาวจากเครื่องวัด
    
  5. ผู้ประกอบการมากไป (แต่ขาดการตรวจสอบประเภทมิติ)
    // ค่อนข้างยุ่ง, buggy, ไม่ปลอดภัยและอาจเป็นไปไม่ได้โดยไม่ใช้ F # หรือ C ++ MPL
    // มันก็จะบอกว่ามิติการวิเคราะห์คือไม่ได้เป็นคุณลักษณะตัวเลือกสำหรับหนี้ -
    // ไม่ว่าคุณจะใช้โดยตรงหรือไม่ มันถูกต้อง
    

0

มีบทความที่ดีใน magazin unfourtunatly เป็นภาษาเยอรมัน: http://www.dotnetpro.de/articles/onlinearticle1398.aspx

แนวคิดพื้นฐานคือการมีคลาสยูนิตเช่นความยาวพร้อมกับ BaseMeasurement คลาสประกอบด้วยปัจจัยการแปลง, ตัวดำเนินการโอเวอร์โหลด, ToString โอเวอร์โหลด, ตัวแยกวิเคราะห์สตริงและการใช้งานเป็นตัวทำดัชนี เราได้ดำเนินการแม้กระทั่งมุมมองทางสถาปัตยกรรม แต่ไม่ได้เผยแพร่ในรูปแบบของห้องสมุด

public class Length : MeasurementBase
    {
        protected static double[] LengthFactors = { 1, 100, 1000, 0.001, 100 / 2.54 };
        protected static string[] LengthSymbols = { "m", "cm", "mm", "km", "in" };
...
      public virtual double this[Units unit]
        {
            get { return BaseValue * LengthFactors[(int)unit]; }
            set { BaseValue = value / LengthFactors[(int)unit]; }
        }
...

        public static ForceDividedByLength operator *(Length length, Pressure pressure1)
        {
            return new ForceDividedByLength(pressure1[Pressure.Units.kNm2] * length[Units.m], ForceDividedByLength.Units.kNm);
        }

...

ดังนั้นคุณจะเห็นการใช้งานกับผู้ใช้งาน Pressure หรือเพียง:

var l = new Length(5, Length.Units.m)    
Area a = l * new Length("5 m");
a.ToString() // -> 25 m^2
double l2 = l[Length.Units.ft];

แต่อย่างที่คุณพูดฉันไม่พบยูนิคอร์นด้วย :)


-1

นี่คือraison d'etreของunitsคำสั่งUnix ซึ่งทำได้ทั้งหมดโดยใช้วิธีการขับเคลื่อนด้วยไฟล์ข้อมูลเพื่อระบุความสัมพันธ์


unitsขอขอบคุณสำหรับการกล่าวขวัญ หน่วยเหตุผลหลักที่ใช้งานไม่ได้สำหรับโซลูชันที่กว้างขึ้นของฉันคือสตริงที่มีรูปแบบอิสระ ได้รับแล้วจะให้ข้อความแสดงข้อผิดพลาดกลับมา แต่วิธีนี้คือการกำหนดเป้าหมายนักพัฒนาที่จะรวมรหัสนี้กับแอปพลิเคชันของเรา สตริงรูปแบบอิสระนำเสนอโอกาสมากเกินไปสำหรับข้อผิดพลาด

1
คุณควรดูunitsไฟล์ข้อมูลของ วิธีที่กำหนดความสัมพันธ์ระหว่างปริมาณนั้นสะอาดมากและอาจเป็นประโยชน์ต่อปัญหาของคุณ
Ross Patterson
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.