C# 中使用 GDI+ 繪圖時,PointF 結構體構造函數參數類型為 float。直接寫 new PointF(6.56, 7.58) 會編譯報錯,因為 C# 數值字面量預設類型推導規則。本文詳細解析類型推導機制、正確寫法、隱式轉換規則與最佳實踐。
// 錯誤代碼
PointF p = new PointF(6.56, 7.58); // CS1503: 無法從 "double" 轉換為 "float"
// 報錯信息
// Argument 1: cannot convert from 'double' to 'float'
// Argument 2: cannot convert from 'double' to 'float'
6.56)預設類型為 double。PointF(float x, float y) 構造函數要求 float 參數。double 到 float 屬於窄化轉換(可能丟失精度),C# 禁止隱式窄化轉換,必須顯式強制轉換或使用 float 字面量。| 寫法 | 代碼 | 原理 | 推薦度 |
|---|---|---|---|
| F 後綴 (標準) | new PointF(6.56f, 7.58f) | 字面量類型直接為 float,無轉換 | ⭐⭐⭐⭐⭐ |
| 強制轉換 | new PointF((float)6.56, (float)7.58) | 顯式窄化轉換,編譯器允許 | ⭐⭐⭐ |
| 變量中轉 | float x = 6.56f; float y = 7.58f; new PointF(x, y); | 變量聲明時已確定類型 | ⭐⭐⭐ |
| 後綴 | 類型 | 示例 | 備註 |
|---|---|---|---|
無 / d/D | double | 3.14 / 3.14d | 預設 |
f/F | float | 3.14f | 單精度 |
m/M | decimal | 3.14m | 高精度貨幣計算 |
u/U | uint/ulong | 100u | 無符號整數 |
l/L | long/ulong | 100L | 長整數 |
// 隱式轉換鏈 (編譯器自動插入)
byte → short → int → long → float → double
↑
char → int
// decimal 無隱式轉換到/從 float/double (精度考量)
// 必須顯式轉換:(float)3.14m 或 3.14f
關鍵點:long → float 是隱式允許的(雖可能丟失精度),但 double → float 禁止隱式,因為 double 精度高於 float,屬於明確窄化。
using (Graphics g = this.CreateGraphics())
using (Pen pen = new Pen(Color.Red, 2))
{
// 繪製折線
PointF[] points = {
new PointF(10.5f, 20.3f),
new PointF(100.7f, 50.1f),
new PointF(150.2f, 120.9f)
};
g.DrawLines(pen, points);
// 繪製字符串 (需 StringFormat)
g.DrawString("Hello", this.Font, Brushes.Black, new PointF(50f, 50f));
// 繪製矩形 (RectangleF)
RectangleF rect = new RectangleF(10f, 10f, 100f, 50f);
g.DrawRectangle(pen, Rectangle.Round(rect)); // 或 g.DrawRectangle(pen, rect.X, rect.Y, rect.Width, rect.Height);
}
PointF、SizeF、RectangleF 構造參數是否加 f 後綴?float 變量時是否顯式轉換 (float)(x * y)?double 變量/屬性賦值給 float 時是否加 (float)?decimal (貨幣) 與 float/double 混用時是否顯式轉換?C# 實數字面量預設為 double,PointF 需要 float,double → float 禁止隱式轉換。給所有浮點字面量加 f 後綴 是最簡單、最安全、性能最好的習慣。這不僅適用於 PointF,還適用於所有 float 參數的 API 調用(WPF、Unity、OpenTK 等)。