.NET มี EventArgs <T> ในตัวหรือไม่


85

ฉันพร้อมที่จะสร้างคลาส EventArgs ทั่วไปสำหรับอาร์กิวเมนต์เหตุการณ์ที่มีอาร์กิวเมนต์เดียว:

public class EventArg<T> : EventArgs
{
    // Property variable
    private readonly T p_EventData;

    // Constructor
    public EventArg(T data)
    {
        p_EventData = data;
    }

    // Property for EventArgs argument
    public T Data
    {
        get { return p_EventData; }
    }
}

ก่อนที่ฉันจะทำเช่นนั้น C # มีคุณสมบัติเดียวกันในภาษาหรือไม่ ฉันจำได้ว่าเคยเจออะไรแบบนั้นตอนที่ C # 2.0 ออกมา แต่ตอนนี้ฉันหาไม่เจอ

หรือกล่าวอีกนัยหนึ่งฉันต้องสร้างคลาส EventArgs ทั่วไปของฉันเองหรือไม่หรือ C # มีให้ ขอบคุณสำหรับความช่วยเหลือของคุณ.


9
คุณอาจเคยเห็นEventhandler<T>
Henk Holterman

1
คุณอาจเคยเห็นEventArgs<T>ในรหัสที่ใช้ CAB / SCSF พบได้บ่อยในแอปพลิเคชัน CAB / SCSF ในขณะที่มันไม่เป็นส่วนหนึ่งของกรอบที่มีเป็น EventArgs <T> การดำเนินงาน
Shaun Wilson

คำตอบ:


68

ไม่คุณอาจกำลังคิดอยู่EventHandler<T>ซึ่งช่วยให้คุณสามารถกำหนดผู้รับมอบสิทธิ์สำหรับ EventArgs ประเภทใดก็ได้

โดยส่วนตัวแล้วฉันไม่รู้สึกว่าEventArgs<T>มันค่อนข้างดีเท่าไหร่ ข้อมูลที่ใช้เป็น "payload" ในเหตุการณ์ args ควรเป็นคลาสที่กำหนดเองเพื่อให้การใช้งานและคุณสมบัติที่คาดหวังชัดเจนมาก การใช้คลาสทั่วไปจะทำให้คุณไม่สามารถใส่ชื่อที่มีความหมายได้ ("ข้อมูล" หมายถึงอะไร)


52
ในแอปพลิเคชันที่มีข้อมูลเป็นศูนย์กลางแอปพลิเคชันที่มีลักษณะคล้าย MPI เป็นเรื่องปกติที่จะเห็น EventArgs <T> ในการประมวลผลข้อมูลเพื่อให้นักพัฒนาสามารถใช้ประโยชน์จากระบบการสมัครสมาชิก / การลงทะเบียนในตัวแบบปลอดภัย (.NET เหตุการณ์และตัวแทน) เนื่องจากไม่มีเหตุผลอย่างยิ่งที่จะสร้างคลาสย่อย EventArgs เพียงเพื่อขนส่งข้อมูล หากเจตนาของคุณคือการขนส่งข้อมูลเนื้อหาที่เหมาะสมกว่าในการกำหนด EventArgs <T> คุณสามารถ subclass สำหรับการใช้งานแบบไม่ต่อเนื่องโดยไม่คำนึงถึงข้อมูลที่กำลังขนส่ง TL: DR ส่วนแรกของคำตอบนี้เป็นข้อเท็จจริงและถูกต้องส่วนที่สองเป็นอัตนัย / ความคิดเห็น
Shaun Wilson

1
ฉันคิดว่าคุณพูดถูก ... ต่อต้านความขี้เกียจที่ทำให้ฉันมาที่นี่ เหมือนกับเวลาที่นักพัฒนาขี้เกียจใช้ Tuple <,> แย่มาก
CRice

จุดที่ดี แต่โดยพื้นฐานแล้วสิ่งนี้จะทำเช่นเดียวกับ Microsoft เมื่อพวกเขาเพิ่มคุณสมบัติแท็กในคลาส Controls แน่นอนเพียงเพราะ MS ทำมันไม่ได้ทำให้ถูกต้อง
Ken Richards

1
ฉันเห็นด้วยกับผู้แสดงความคิดเห็นคนแรกครึ่งหลังทั้งหมดของคำตอบนี้เป็นความคิดเห็นส่วนตัว / หลักศาสนาที่ไม่สร้างสรรค์ :(
BrainSlugs83

6
วิธีการที่ไม่EventHandler <ลูกค้า>หรือEventHandler <คำสั่งซื้อ>ถ่ายทอดข้อมูลใด ๆ ที่น้อยกว่าCustomerEventHandlerหรือOrderEventHandler ?
Quarkly

33

ฉันต้องบอกว่าฉันไม่เข้าใจ 'คนเจ้าระเบียบ' ทั้งหมดที่นี่ เช่นถ้าคุณมีคลาสกระเป๋าที่กำหนดไว้แล้ว - ซึ่งมีข้อมูลจำเพาะคุณสมบัติและอื่น ๆ ทั้งหมด - ทำไมแฮ็คจึงสร้างคลาสพิเศษที่ไม่จำเป็นขึ้นมาเพื่อให้สามารถทำตามกลไกเหตุการณ์ / อาร์กิวเมนต์สไตล์ลายเซ็นได้? ไม่ใช่ทุกอย่างที่อยู่ใน. NET - หรือ 'หายไปจาก' สำหรับเรื่องนั้น - เป็นสิ่งที่ 'ดี' - MS 'แก้ไข' ตัวเองมาหลายปีแล้ว ... ฉันจะบอกว่าแค่ไปสร้างมันขึ้นมาเหมือนที่ฉันทำ - เพราะฉันต้องการมันแบบนั้น - และช่วยฉันประหยัดเวลาได้มาก


3
ในกรณีนี้ประเด็น 'คนเจ้าระเบียบ' คือการตั้งใจให้ชัดเจนที่สุด ในแอปที่ใช้งานจริงฉันมีคลาส EventArgs เหล่านี้มากมาย หนึ่งปีต่อจากนี้มันจะง่ายขึ้นที่จะเข้าใจสิ่งที่ฉันทำถ้าฉันทำตามคำแนะนำของรีดและสร้างคลาส EventArgs ที่กำหนดเอง
David Veeneman

9
ไม่ได้หมายถึงการติดป้ายชื่อใคร :) จุดอยู่ใน 'ทั่วไป' ในเหตุการณ์ - หากคุณต้องการเพียงแค่กิจกรรมที่แตกต่างกันโหลก็โอเค แต่ถ้าคุณไม่ทราบธรรมชาติของ T ล่วงหน้าซึ่งเป็นที่รู้จักเฉพาะในรันไทม์ - คุณก็ต้องมีเหตุการณ์ทั่วไป ดังนั้นหากคุณมีแอปที่เป็นส่วนที่ดีในการจัดการกับยาสามัญไม่ทราบจำนวน # โดยพลการคุณก็ต้องมีเหตุการณ์ทั่วไปด้วย หรือกล่าวคือไม่มีวิธีแก้ปัญหาที่สะอาดสำหรับทุกปัญหากฎง่ายๆเป็นเพียงกฎง่ายๆ - และนั่นคือสิ่งที่ฉันหมายถึงโดยคนเจ้าระเบียบวิธีแก้ปัญหาแต่ละอย่างแตกต่างกันคุณต้องชั่งน้ำหนักสิ่งต่างๆข้อดีและข้อเสีย
NSGaga ส่วนใหญ่ - ไม่ได้ใช้งาน

2
การออกแบบไม่ใช่สีดำและสีขาวดังนั้นฉันจึงเห็นด้วยกับ NSGaga ที่นี่ บางครั้ง "รวดเร็วและสกปรก" ก็เหมาะสม ภาษาควรมีคุณลักษณะที่หลากหลายเพื่อให้เหมาะกับการใช้งานส่วนใหญ่ ควรขึ้นอยู่กับนักพัฒนาในการตัดสินใจว่าอะไรเหมาะสม ครั้งสุดท้ายที่ MS พยายามบังคับให้ออกแบบ "ดี" โดยการ จำกัด ภาษาคือ WPF เมื่อพวกเขาพยายามบังคับใช้ XAML โดยทำให้.
Robear

9

มันมีอยู่จริง อย่างน้อยก็ทำตอนนี้

คุณสามารถค้นหาDataEventArgs<TData>ในบางแตกต่างกันประกอบไมโครซอฟท์ / namespaces เช่นMicrosoft.Practices.Prism.Events อย่างไรก็ตามนี่คือเนมสเปซที่คุณอาจไม่พบว่าปกติจะรวมไว้ในโปรเจ็กต์ของคุณดังนั้นคุณอาจใช้การใช้งานของคุณเอง


ฉันพยายามค้นหาคำแนะนำและข้อควรพิจารณาเกี่ยวกับเวลาและเหตุผลที่จะใช้คลาส EventArgs ทั่วไปเช่นนี้ ดูสิ่งนี้ด้วย: stackoverflow.com/questions/15766219/…
Ulf Åkerstedt

ข้อควรระวังบางประการเมื่อตัดสินใจใช้ EventArgs ทั่วไป: stackoverflow.com/questions/129453/…
Ulf Åkerstedt

7

ในกรณีที่คุณเลือกที่จะไม่ใช้ปริซึมแต่ยังคงต้องการที่จะลองทั่วไปEventArgsเข้าใกล้

public class GenericEventArgs<T> : EventArgs
{
    public T EventData { get; private set; }

    public GenericEventArgs(T EventData)
    {
        this.EventData = EventData;
    }
}

// ใช้โค้ดตัวอย่างต่อไปนี้เพื่อประกาศเหตุการณ์ObjAdded

public event EventHandler<GenericEventArgs<TargetObjType>> ObjAdded;

// ใช้โค้ดตัวอย่างต่อไปนี้เพื่อเพิ่มเหตุการณ์ObjAdded

private void OnObjAdded(TargetObjType TargetObj)
{
    if (ObjAdded!= null)
    {
        ObjAdded.Invoke(this, new GenericEventArgs<TargetObjType>(TargetObj));
    }
}

// และ finnaly คุณสามารถสมัครกิจกรรมObjAddedของคุณได้

SubscriberObj.ObjAdded +=  (object sender, GenericEventArgs<TargetObjType> e) =>
{
    // Here you can explore your e.EventData properties
};

3

ไม่มี ARGS ทั่วไปในตัว ถ้าคุณทำตามรูปแบบของ Microsoft EventHandler แล้วคุณใช้ EventArgs public class MyStringChangedEventArgs : EventArgs { public string OldValue { get; set; } }มาของคุณเช่นคุณแนะนำ:

อย่างไรก็ตาม - หากไกด์สไตล์ทีมของคุณยอมรับการทำให้เข้าใจง่าย - โปรเจ็กต์ของคุณสามารถใช้เหตุการณ์ที่มีน้ำหนักเบาเช่นนี้:

public event Action<object, string> MyStringChanged;

การใช้งาน:

// How to rise
private void OnMyStringChanged(string e)
{
    Action<object, string> handler = MyStringChanged;    // thread safeness
    if (handler != null)
    {
        handler(this, e);
    }
}

// How to handle
myObject.MyStringChanged += (sender, e) => Console.WriteLine(e);

โดยปกติโครงการ PoC จะใช้แนวทางหลัง อย่างไรก็ตามในแอปพลิเคชันระดับมืออาชีพโปรดทราบถึงเหตุผลของตำรวจ FX # CA1009: https://msdn.microsoft.com/en-us/library/ms182133.aspx


1

ปัญหาเกี่ยวกับประเภททั่วไปคือแม้ว่า DerivedType จะสืบทอดจาก BaseType แต่ EventArgs (DerivedType) จะไม่สืบทอดจาก EventArgs (BaseType) การใช้ EventArgs (BaseType) จะป้องกันในภายหลังโดยใช้เวอร์ชันที่ได้รับมา


2
นี่เป็นเท็จอย่างเห็นได้ชัด โปรดดู "Covariance and Contravariance in Generics - Microsoft.com" msdn.microsoft.com/en-us/library/dd799517.aspx
Shaun Wilson

1
@ShaunWilson: สิ่งที่เป็นเท็จ? หนึ่งสามารถกำหนดอินเตอร์เฟซที่ covariant แต่ชั้นเรียนเท่านั้นที่สามารถทั่วไปเกี่ยวกับการพารามิเตอร์ประเภททั่วไปเป็นผู้ได้รับมอบหมายที่จะไม่ได้รับการเลี้ยงดูด้วยIEventArgs Delegate.Combineผู้รับมอบสิทธิ์ที่จะใช้ด้วยDelegate.Combineไม่ควรเป็นคนที่มีความสัมพันธ์ทางเพศเนื่องจากอาจมีการจัดเก็บตัวอย่างเช่นAction<DerivedType>ลงในช่องประเภทAction<BaseType>แต่การพยายามทำในภายหลังCombineด้วยกรณีAction<BaseType>จะล้มเหลว
supercat

-4

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

หากคุณไม่ต้องการเพียงแค่สตริงหรือสิ่งที่คล้ายคลึงกันสำหรับกระเป๋าข้อมูลของคุณซึ่งในกรณีนี้อาจมีคลาส EventArgs ใน. NET ซึ่งมีไว้เพื่อตอบสนองวัตถุประสงค์ง่ายๆที่คุณได้รับ


-1. ตอนนี้ฉันมีข้อควรระวังนี้อย่างแน่นอนและน้ำหนักบรรทุกของฉันจะเป็นวัตถุที่ไม่เปลี่ยนรูปซึ่งเป็น "ข้อความ" ที่มาจากรถประจำทาง ... และในที่อื่น ๆ ด้วย EventArgs แบบกำหนดเอง .... สร้างคลาสซ้ำซ้อนที่นี่ ผิดปกติ แต่แอปพลิเคชันเป็นเช่นนั้น
TomTom
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.