0Pricing
C# Academy · บทเรียน

คณิตศาสตร์แบบเจเนอริก (ภาพรวม) และแอตทริบิวต์แบบเจเนอริก (เมื่อเหมาะสม)

จำลองคณิตศาสตร์แบบเจเนอริกโดยไม่ใช้ฟีเจอร์สมัยใหม่: ส่งตัวให้บริการการดำเนินการหรือ delegate จำกัดชนิดอย่างรอบคอบ และจำลอง “แอตทริบิวต์แบบเจเนอริก” ผ่านพารามิเตอร์ Type

คณิตศาสตร์แบบเจเนอริก (ภาพรวม) และแอตทริบิวต์แบบเจเนอริก (เมื่อเหมาะสม) เป็นบทเรียน C# Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 3 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน C# Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส C# Academy มีบทเรียนทั้งหมด 3 บทเรียน

คณิตศาสตร์ทั่วไปใน C# 6

เป้าหมาย: เขียนอัลกอริทึมตัวเลขแบบชนิดทั่วไปใน C# 6

  • ไม่มีตัวดำเนินการแบบนามธรรมสถิตบน T
  • แนวทางแก้: อินเทอร์เฟซ ตัวให้บริการการดำเนินการ หรือ ฟังก์ชันตัวแทน ขนาดเล็ก
  • สำหรับคำอธิบายกำกับ ให้ใช้ แอตทริบิวต์ที่รับพารามิเตอร์ Type

รูปแบบตัวให้บริการการดำเนินการ

จัดเตรียม ศูนย์ และ Add ผ่านอินเทอร์เฟซ อัลกอริทึมชนิดทั่วไปจะเรียกเมธอดเหล่านั้นแทนการใช้เครื่องหมายบวกกับ T

using System;
using System.Collections.Generic;

public interface INumericOps<T>
{
  T Zero { get; }
  T Add(T a, T b);
}

public sealed class IntOps : INumericOps<int>
{
  public int Zero { get { return 0; } }
  public int Add(int a, int b) { return a + b; }
}

public sealed class DoubleOps : INumericOps<double>
{
  public double Zero { get { return 0.0; } }
  public double Add(double a, double b) { return a + b; }
}

public class Program
{
  static T Sum<T>(IEnumerable<T> items, INumericOps<T> ops)
  {
    T acc = ops.Zero;
    foreach (T x in items) acc = ops.Add(acc, x);
    return acc;
  }

  public static void Main(string[] args)
  {
    int s1 = Sum(new int[] {1,2,3}, new IntOps());
    double s2 = Sum(new double[] {1.5, 2.0}, new DoubleOps());
    Console.WriteLine("Sum int = " + s1);
    Console.WriteLine("Sum double = " + s2);
  }
}

หาค่าเฉลี่ยด้วยตัวช่วย

สำหรับการดำเนินการที่ไม่สามารถเขียนแบบชนิดทั่วไปได้ เช่น การหาร ให้ส่ง ตัวแปลง ขนาดเล็กหรือฟังก์ชันตัวแทนเพิ่มเติมเข้าไป

using System;
using System.Collections.Generic;

public interface INumericOps<T>
{
  T Zero { get; }
  T Add(T a, T b);
}

public sealed class DoubleOps : INumericOps<double>
{
  public double Zero { get { return 0.0; } }
  public double Add(double a, double b) { return a + b; }
}

public class Program
{
  static double Average<T>(IEnumerable<T> items, INumericOps<T> ops, Func<T,double> toDouble)
  {
    T acc = ops.Zero;
    int count = 0;
    foreach (T x in items) { acc = ops.Add(acc, x); count++; }
    if (count == 0) throw new ArgumentException("Empty sequence", "items");
    // convert with a delegate for division
    return toDouble(acc) / count;
  }

  public static void Main(string[] args)
  {
    double avg = Average<double>(new double[] {2.0, 4.0, 6.0}, new DoubleOps(), delegate(double d) { return d; });
    Console.WriteLine("Avg = " + avg);
  }
}

การพับสะสมด้วยฟังก์ชันตัวแทน

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

using System;

public class Program
{
  static T Fold<T>(T[] xs, T seed, Func<T,T,T> combine)
  {
    T acc = seed;
    for (int i = 0; i < xs.Length; i++) acc = combine(acc, xs[i]);
    return acc;
  }

  public static void Main(string[] args)
  {
    int sum = Fold<int>(new int[] {1,2,3}, 0, delegate(int a, int b) { return a + b; });
    double sumD = Fold<double>(new double[] {1.5, 2.5}, 0.0, delegate(double a, double b) { return a + b; });
    Console.WriteLine("Sum ints = " + sum);
    Console.WriteLine("Sum doubles = " + sumD);
  }
}

ทางเลือกสำหรับแอตทริบิวต์

C# 6 ไม่มี แอตทริบิวต์แบบชนิดทั่วไปที่แท้จริง ให้ส่ง Type ไปยังแอตทริบิวต์เพื่อระบุชนิดทั่วไปที่เกี่ยวข้อง

using System;
using System.Reflection;

// C# 6 cannot declare generic attributes. Workaround: pass a Type.
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public sealed class ValidatorForAttribute : Attribute
{
  public Type TargetType { get; private set; }
  public ValidatorForAttribute(Type targetType) { TargetType = targetType; }
}

public sealed class Customer { public string Name; }

[ValidatorFor(typeof(Customer))]
public sealed class CustomerValidator
{
  public bool IsValid(Customer c) { return c != null && !string.IsNullOrEmpty(c.Name); }
}

public class Program
{
  public static void Main(string[] args)
  {
    Type t = typeof(CustomerValidator);
    object[] attrs = t.GetCustomAttributes(typeof(ValidatorForAttribute), false);
    if (attrs.Length > 0)
    {
      ValidatorForAttribute a = (ValidatorForAttribute)attrs[0];
      Console.WriteLine("Validator targets: " + a.TargetType.Name);
    }
  }
}

เคล็ดลับและทางเลือก

เคล็ดลับ:

  • เลือกใช้ ตัวให้บริการการดำเนินการ สำหรับอัลกอริทึมตัวเลขที่นำกลับมาใช้ซ้ำได้
  • ใช้ ฟังก์ชันตัวแทน สำหรับตัวช่วยขนาดเล็ก เช่น การรวมค่าและการแปลงค่า
  • สำหรับคำอธิบายกำกับ ให้ส่ง Type ในแอตทริบิวต์แล้วอ่านค่าผ่านการตรวจสอบชนิดแบบสะท้อน

แนวทางแก้สำหรับคณิตศาสตร์ชนิดทั่วไป

ตรวจสอบสั้น ๆ: ใน C# 6 วิธีปฏิบัติในการเขียนฟังก์ชันหาผลรวมชนิดทั่วไปโดยไม่ใช้คณิตศาสตร์ชนิดทั่วไปสมัยใหม่คืออะไร

สรุปทบทวน

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

คำถามที่พบบ่อย

บทเรียน “คณิตศาสตร์แบบเจเนอริก (ภาพรวม) และแอตทริบิวต์แบบเจเนอริก (เมื่อเหมาะสม)” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “คณิตศาสตร์แบบเจเนอริก (ภาพรวม) และแอตทริบิวต์แบบเจเนอริก (เมื่อเหมาะสม)” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส C# Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส C# Academy มีบทเรียนทั้งหมด 3 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “คณิตศาสตร์แบบเจเนอริก (ภาพรวม) และแอตทริบิวต์แบบเจเนอริก (เมื่อเหมาะสม)”

จำลองคณิตศาสตร์แบบเจเนอริกโดยไม่ใช้ฟีเจอร์สมัยใหม่: ส่งตัวให้บริการการดำเนินการหรือ delegate จำกัดชนิดอย่างรอบคอบ และจำลอง “แอตทริบิวต์แบบเจเนอริก” ผ่านพารามิเตอร์ Type คุณปฏิบัติ C# Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน C# Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน C# Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 2 จากทั้งหมด 3 บทเรียน

บทเรียน “คณิตศาสตร์แบบเจเนอริก (ภาพรวม) และแอตทริบิวต์แบบเจเนอริก (เมื่อเหมาะสม)” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน C# Academy นี้ได้ไหม

ได้ บทเรียน C# Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. unmanaged, notnull, new() (จำลองใน C# 6)
  2. คณิตศาสตร์แบบเจเนอริก (ภาพรวม) และแอตทริบิวต์แบบเจเนอริก (เมื่อเหมาะสม)
  3. เครื่องมือเจเนอริกที่นำกลับมาใช้ซ้ำได้
← กลับไปที่ C# Academy