การสืบทอดความคิดเห็นสำหรับ C # (จริงๆแล้วภาษาใดก็ได้)


95

สมมติว่าฉันมีอินเทอร์เฟซนี้

public interface IFoo
{
    ///<summary>
    /// Foo method
    ///</summary>
    void Foo();

    ///<summary>
    /// Bar method
    ///</summary>
    void Bar();

    ///<summary>
    /// Situation normal
    ///</summary>
    void Snafu();
}

และชั้นนี้

public class Foo : IFoo
{
    public void Foo() { ... }
    public void Bar() { ... }
    public void Snafu() { ... }
}

มีวิธีหรือมีเครื่องมือที่สามารถให้ฉันใส่ความคิดเห็นของสมาชิกแต่ละคนในคลาสพื้นฐานหรืออินเทอร์เฟซโดยอัตโนมัติได้หรือไม่?

เพราะฉันเกลียดการเขียนความคิดเห็นเดิมซ้ำสำหรับคลาสย่อยที่ได้รับแต่ละคลาส!


14
ฉันไม่เพียง แต่เกลียดมันเท่านั้น แต่ยังยากที่จะทำให้ข้อมูลเหล่านั้นตรงกันอีกด้วย
Olivier Jacot-Descombes

คำตอบ:


17

GhostDocทำอย่างนั้น สำหรับวิธีการที่ไม่ได้รับการสืบทอดมานั้นจะพยายามสร้างคำอธิบายจากชื่อ

FlingThing() กลายเป็น "Flings the Thing"


2
GhostDoc นั้นยอดเยี่ยมมากสิ่งหนึ่งที่ฉันไม่รู้ว่าฉันต้องการ แต่ตอนนี้ไม่สามารถทำได้โดยไม่ต้อง: o)
NikolaiDante

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

8
@Lensflare นี่คือเรื่องจริง ครั้งหนึ่งฉันต้องใช้กรอบงานที่มีเฉพาะความคิดเห็นที่สร้างขึ้นซึ่งเพิ่มข้อมูล NO ให้กับวิธีการ / คลาส แทนที่จะเป็น "วิธีนี้ทำสิ่งนี้และ" ความคิดเห็นที่ชอบ "นี่คือวิธี XY ของคลาส Z" xD นอกจากนี้คุณยังไม่ได้เรียกดูโค้ดดังนั้นจึงต้องลองผิดลองถูก ไม่มีอีกครั้ง! :-)
itmuckel

15
@Lensflare ในขณะที่ฉันเห็นด้วยกับคุณ 100% เท่าที่อาศัย AGD เหมือนเดิม แต่ฉันควรชี้ให้เห็นว่า AGD ไม่ได้มีไว้เพื่อใช้เป็นปุ่มมายากล แทนที่จะใช้เป็นตัวสร้างเทมเพลตเพื่อลดปริมาณของสำเร็จรูปเอกสารซ้ำ ๆ ที่คุณต้องเขียนด้วยตัวเองเพื่อให้คุณสามารถมุ่งเน้นไปที่สิ่งที่สำคัญได้ --- ยกตัวอย่างเช่นมันสามารถสร้าง<summary>, <param>, <returns>, <throws>, etc...ส่วนสำหรับคุณ หลายครั้งด้วยผลลัพธ์ที่ดีเพียงพอ เวลาอื่น ๆ ที่ต้องการการแก้ไขหรือขยาย แต่ยังคงลดความพยายามโดยรวม
XenoRo

5
ผู้คนที่เอกสารประกอบไม่ได้มีไว้สำหรับนักพัฒนา แต่สำหรับสถาปนิกดังนั้นพวกเขาจึงครอบคลุมก้นของพวกเขาทั้งหมด: "เฮ้เราสามารถอ่านเอกสารรหัสของโครงการของคุณได้หรือไม่ได้นี่คือ"
Trident D'Gao

157

คุณสามารถใช้<inheritdoc />แท็กได้ตลอดเวลา:

public class Foo : IFoo
{
    /// <inheritdoc />
    public void Foo() { ... }
    /// <inheritdoc />
    public void Bar() { ... }
    /// <inheritdoc />
    public void Snafu() { ... }
}

เมื่อใช้crefแอตทริบิวต์นี้คุณสามารถอ้างถึงสมาชิกที่แตกต่างกันโดยสิ้นเชิงในคลาสหรือเนมสเปซที่แตกต่างกันโดยสิ้นเชิง!

public class Foo
{
    /// <inheritdoc cref="System.String.IndexOf" />
    public void Bar() { ... } // this method will now have the documentation of System.String.IndexOf
}

8
ฉันไม่รู้ว่ามี <inheritdoc /> อยู่ด้วยซ้ำ ... แต่เท่าที่ฉันเห็นความคิดเห็นของวิธีนี้ไม่ปรากฏพร้อมกับ intellisense
gerleim

12
@gerleim ดูคำตอบของ Jeff Heaton จากปีก่อนและความคิดเห็นด้านล่าง Sandcastle มี <inheritdoc /> ไม่ใช่ C #
rbwhitaker

4
ฉันเห็นความคิดเห็นจากอินเทอร์เฟซใน intellisense กับ inheritdoc และถ้าไม่มี code-doc เลยในคลาสที่ได้รับ แต่นั่นอาจเป็นเพราะฉันมีความคมกว่า
Tim Abell

9
Resharper 2017.2 ได้ปรับปรุงการสนับสนุนสำหรับ inheritdoc jetbrains.com/resharper/whatsnew
Dav Evans

4
Visual Studio Enterprise 2017 (เวอร์ชัน 15.9.3) ไม่แสดงความคิดเห็นที่สืบทอดมาให้ฉัน
herzbube

26

ใช้/// <inheritdoc/>ถ้าคุณต้องการมรดก หลีกเลี่ยง GhostDoc หรืออะไรทำนองนั้น

ฉันยอมรับว่าเป็นเรื่องน่ารำคาญที่ความคิดเห็นไม่ได้รับการสืบทอด มันจะเป็นส่วนเสริมที่ค่อนข้างง่ายในการสร้างถ้ามีคนมีเวลา (ฉันหวังว่าฉันจะทำ)

ที่กล่าวว่าในฐานรหัสของเราเราใส่ความคิดเห็น XML บนอินเทอร์เฟซเท่านั้นและเพิ่มความคิดเห็นการใช้งานเพิ่มเติมให้กับชั้นเรียน สิ่งนี้ใช้ได้ผลกับเราเนื่องจากชั้นเรียนของเราเป็นแบบส่วนตัว / ภายในและเฉพาะอินเทอร์เฟซเท่านั้นที่เป็นแบบสาธารณะ เมื่อใดก็ตามที่เราใช้วัตถุผ่านทางอินเทอร์เฟซเราจะแสดงความคิดเห็นแบบเต็มใน intellisence

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


ฉันสับสน - คุณบอกว่าให้หลีกเลี่ยง GhostDoc แต่ในตอนท้ายดูเหมือนว่าคุณรับรอง GhostDoc ช่วยให้สิ่งต่างๆง่ายขึ้น คุณช่วยชี้แจงได้ไหมว่าคุณหมายถึงอะไร?
Mike Marynowski

ขอบคุณ @MikeMarynowski นี่เป็นคำแนะนำเก่า ผมคิดว่าผมอยากจะบอกว่าในเวลาที่ GhostDoc เช่นเครื่องกำเนิดไฟฟ้าอื่น ๆ จะเพิ่มความคิดเห็น <param name="origin">The origin.</param>แต่มีรายละเอียดที่เกือบจะไร้ประโยชน์เช่น ดูghostdoc พูดว่าสิ่งที่เลวร้ายที่สุดสำหรับตัวอย่างเพิ่มเติม Visual Studio มีการสร้างขุยและเครื่องกำเนิดไฟฟ้าที่ดีขึ้นมากสำหรับ xmldocs เพื่อแจ้งให้คุณทราบเมื่อพารามิเตอร์ + เอกสารไม่สอดคล้องกันดังนั้น GhostDoc (หรือเครื่องมืออื่น ๆ ) จึงไม่จำเป็นอีกต่อไป
Dennis

15

Java มีสิ่งนี้และฉันใช้มันตลอดเวลา แค่ทำ:

/**
 * {@inheritDoc}
 */

และเครื่องมือ Javadoc ก็คิดออก

C # มีเครื่องหมายคล้ายกัน:

<inheritDoc/>

คุณสามารถอ่านเพิ่มเติมได้ที่นี่:

http://www.ewoodruff.us/shfbdocs/html/79897974-ffc9-4b84-91a5-e50c66a0221d.htm


37
C # ไม่มี<inheritdoc/>เครื่องหมาย: Sandcastleมีอยู่ shfb.codeplex.com
Eric Dand

8
มีการร้องขอคุณสมบัติเสียงของผู้ใช้เพื่อเพิ่ม <inheritdoc /> ไปที่ C # เข้าไปโหวตได้ที่visualstudio.uservoice.com/forums/121579-visual-studio/…
Deadlydog

1
ทั้ง C # หรือ Java (หรือภาษาโปรแกรมอื่น ๆ ) ไม่มีองค์ประกอบ "XML doc" ใด ๆ เหล่านี้เป็นความคิดเห็น คอมไพเลอร์ไม่ทราบเกี่ยวกับพวกเขา พวกเขาทั้งหมดถูกใช้อย่างเข้มงวดโดยเครื่องกำเนิดเอกสารของบุคคลที่สามไม่ว่าจะเป็น javadoc หรือ sandcastle หรืออะไรก็ตาม
James Curran

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

2
Visual Studio เวอร์ชัน 16.4.0 และใหม่กว่าให้ intellisense สำหรับ <inheritDoc />! docs.microsoft.com/en-us/visualstudio/releases/2019/…
ashbygeek

11

ฉันจะบอกว่าให้ใช้ไฟล์

/// <inheritdoc cref="YourClass.YourMethod"/>  --> For methods inheritance

และ

/// <inheritdoc cref="YourClass"/>  --> For directly class inheritance

คุณต้องใส่ความคิดเห็นนี้ไว้ในบรรทัดก่อนหน้าของคลาส / วิธีการของคุณ

สิ่งนี้จะได้รับข้อมูลความคิดเห็นของคุณเช่นจากอินเทอร์เฟซที่คุณได้บันทึกไว้เช่น:

    /// <summary>
    /// This method is awesome!
    /// </summary>
    /// <param name="awesomeParam">The awesome parameter of the month!.</param>
    /// <returns>A <see cref="AwesomeObject"/> that is also awesome...</returns>
    AwesomeObject CreateAwesome(WhateverObject awesomeParam);

ขอบคุณสำหรับคำแนะนำ! แนวทางนี้มีความชัดเจนมากขึ้นและแก้ปัญหาของคำอธิบายคลาสการสืบทอดจากคลาสอ็อบเจ็กต์ (แม้ว่าจะใช้อินเทอร์เฟซ)
Denis Babarykin

8

Resharper มีตัวเลือกในการคัดลอกข้อคิดเห็นจากคลาสพื้นฐานหรืออินเทอร์เฟซ


1
โอ้? อย่างไร? ฉันใช้ ReSharper และฉันไม่เคยเห็นตัวเลือกนั้นเมื่อใช้งานหรือสืบทอดอินเทอร์เฟซ ... อยู่ที่ไหนและคุณใช้ตัวเลือกนั้นอย่างไร
Jazimov

2
@Jazimov เมื่อคุณ Alt + ป้อนวิธีการแทนที่จะมีตัวเลือกในการ "คัดลอกเอกสารจากฐาน"
svick

8

อีกวิธีหนึ่งคือการใช้<see />แท็กเอกสาร XML นี่เป็นความพยายามพิเศษ แต่ได้ผลนอกกรอบ ...

นี่คือตัวอย่างบางส่วน:

/// <summary>
/// Implementation of <see cref="IFoo"/>.
/// </summary>
public class Foo : IFoo
{
    /// <summary>
    /// See <see cref="IFoo"/>.
    /// </summary>
    public void Foo() { ... }

    /// <summary>
    /// See <see cref="IFoo.Bar"/>
    /// </summary>
    public void Bar() { ... }

    /// <summary>
    /// This implementation of <see cref="IFoo.Snafu"/> uses the a caching algorithm for performance optimization.
    /// </summary>
    public void Snafu() { ... }
}

อัปเดต:

ตอนนี้ฉันชอบใช้/// <inheritdoc/>ซึ่งตอนนี้รองรับโดย ReSharper


1

ฉันลงเอยด้วยการสร้างเครื่องมือเพื่อโพสต์กระบวนการไฟล์เอกสาร XML เพื่อเพิ่มการสนับสนุนสำหรับการแทนที่<inheritdoc/>แท็กในไฟล์เอกสาร XML ด้วยตัวเอง มีจำหน่ายที่www.inheritdoc.io (มีเวอร์ชันฟรี)


0

มีวิธีแก้ปัญหาแบบเนทีฟชนิดหนึ่งที่ฉันพบสำหรับ. NET Core 2.2

แนวคิดคือการใช้<include>แท็ก

คุณสามารถเพิ่ม<GenerateDocumentationFile>true</GenerateDocumentationFile>ของคุณ.csprojไฟล์

คุณอาจมีอินเทอร์เฟซ:

namespace YourNamespace
{
    /// <summary>
    /// Represents interface for a type.
    /// </summary>
    public interface IType
    {
        /// <summary>
        /// Executes an action in read access mode.
        /// </summary>
        void ExecuteAction();
    }
}

และสิ่งที่สืบทอดมาจากมัน:

using System;

namespace YourNamespace
{
    /// <summary>
    /// A type inherited from <see cref="IType"/> interface.
    /// </summary>
    public class InheritedType : IType
    {
        /// <include file='bin\Release\netstandard2.0\YourNamespace.xml' path='doc/members/member[@name="M:YourNamespace.IType.ExecuteAction()"]/*'/>
        public void ExecuteAction() => Console.WriteLine("Action is executed.");
    }
}

โอเคมันค่อนข้างน่ากลัว แต่มันเพิ่มองค์ประกอบที่คาดหวังให้กับไฟล์YourNamespace.xml.

หากคุณสร้างDebugการกำหนดค่าคุณสามารถสลับReleaseสำหรับDebugในfileแอตทริบิวต์ของincludeแท็ก

เพื่อหาที่ถูกต้องmemberคือnameการอ้างอิงเพียงแค่สร้างเปิดDocumentation.xmlไฟล์

ฉันยังคิดว่าวิธีนี้ต้องสร้างโครงการหรือโซลูชันอย่างน้อยสองครั้ง (ครั้งแรกในการสร้างไฟล์ XML เริ่มต้นและครั้งที่สองเพื่อคัดลอกองค์ประกอบจากมันไปยังตัวมันเอง)

ด้านสว่างคือ Visual Studio ตรวจสอบความถูกต้องขององค์ประกอบที่คัดลอกดังนั้นจึงง่ายกว่ามากในการเก็บเอกสารและโค้ดให้ซิงค์กับอินเทอร์เฟซ / คลาสฐาน ฯลฯ (เช่นชื่อของอาร์กิวเมนต์ชื่อพารามิเตอร์ชนิด ฯลฯ )

ในโครงการของฉันฉันได้ลงเอยด้วยทั้ง<inheritdoc/>(สำหรับ DocFX) และ<include/>(สำหรับการเผยแพร่แพ็คเกจ NuGet และสำหรับการตรวจสอบที่ Visual Studio):

        /// <inheritdoc />
        /// <include file='bin\Release\netstandard2.0\Platform.Threading.xml' path='doc/members/member[@name="M:Platform.Threading.Synchronization.ISynchronization.ExecuteReadOperation(System.Action)"]/*'/>
        public void ExecuteReadOperation(Action action) => action();
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.