ฉันสามารถเพิ่มวิธีการขยายไปยังคลาสแบบคงที่ที่มีอยู่ได้หรือไม่


534

ฉันเป็นแฟนตัวยงของวิธีการขยายใน C # แต่ยังไม่เคยประสบความสำเร็จในการเพิ่มวิธีการขยายไปยังระดับคงที่เช่นคอนโซล

ตัวอย่างเช่นถ้าฉันต้องการเพิ่มส่วนขยายใน Console เรียกว่า 'WriteBlueLine' เพื่อให้ฉันไปได้:

Console.WriteBlueLine("This text is blue");

ฉันลองวิธีนี้โดยการเพิ่มวิธีการคงที่ในที่สาธารณะโดยใช้คอนโซลเป็นพารามิเตอร์ 'this' ... แต่ไม่มีลูกเต๋า!

public static class Helpers {
    public static void WriteBlueLine(this Console c, string text)
    {
        Console.ForegroundColor = ConsoleColor.Blue;
        Console.WriteLine(text);
        Console.ResetColor();
    }
}

สิ่งนี้ไม่ได้เพิ่มวิธี 'WriteBlueLine' ลงในคอนโซล ... ฉันทำผิดหรือเปล่า หรือขอสิ่งที่เป็นไปไม่ได้?


3
โอ้ดี โชคร้าย แต่ฉันคิดว่าฉันจะผ่านไป ฉันยังคงเป็นวิธีการส่วนขยายที่บริสุทธิ์ (ในรหัสการผลิตอยู่แล้ว) บางทีวันหนึ่งถ้าฉันโชคดี
Andy McClothing

ฉันเขียนส่วนขยาย HtmlHelper จำนวนหนึ่งสำหรับ ASP.NET MVC เขียนหนึ่งสำหรับ DateTime เพื่อให้ฉันสิ้นสุดวันที่ที่กำหนด (23: 59.59) มีประโยชน์เมื่อคุณขอให้ผู้ใช้ระบุวันที่สิ้นสุด แต่ต้องการให้มันเป็นวันสุดท้าย
tvanfosson

12
ยังไม่มีวิธีเพิ่มในขณะนี้เนื่องจากคุณลักษณะนี้ไม่มีอยู่ใน C # ไม่ใช่เพราะมันเป็นไปไม่ได้สำหรับทุกคน แต่เนื่องจาก C # peeps ยุ่งมากส่วนใหญ่ให้ความสนใจในวิธีการขยายเพื่อให้งาน LINQ และไม่เห็นประโยชน์เพียงพอในวิธีการขยายแบบคงที่เพื่อปรับเวลาที่พวกเขาจะนำมาใช้ เอริค Lippert อธิบายที่นี่
Jordan Gray

1
แค่โทรหาHelpers.WriteBlueLine(null, "Hi");:)
HüseyinYağlı

คำตอบ:


285

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

 public static class ConfigurationManagerWrapper
 {
      public static ConfigurationSection GetSection( string name )
      {
         return ConfigurationManager.GetSection( name );
      }

      .....

      public static ConfigurationSection GetWidgetSection()
      {
          return GetSection( "widgets" );
      }
 }

8
@ Luis - ในบริบทความคิดจะเป็น "ฉันสามารถเพิ่มวิธีการขยายไปยังคลาส ConfigurationManager เพื่อรับส่วนเฉพาะหรือไม่" คุณไม่สามารถเพิ่มเมธอดส่วนขยายให้กับคลาสแบบสแตติกเนื่องจากต้องการอินสแตนซ์ของวัตถุ แต่คุณสามารถเขียนคลาส wrapper (หรือด้านหน้า) ที่ใช้ลายเซ็นเดียวกันและกำหนดการโทรจริงไปยัง ConfigurationManager จริง คุณสามารถเพิ่มวิธีใดก็ได้ที่คุณต้องการในคลาส wrapper ดังนั้นจึงไม่จำเป็นต้องเป็นส่วนเสริม
tvanfosson

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

1
@tap - เป็นเพียงตัวอย่างและอันแรกที่นึกได้ แม้ว่าหลักการความรับผิดชอบเพียงประการเดียวจะเกิดขึ้น "คอนเทนเนอร์" ควรรับผิดชอบในการตีความตัวเองจากไฟล์กำหนดค่าหรือไม่ ปกติฉันมี ConfigurationSectionHandler และส่งเอาต์พุตจาก ConfigurationManager ไปยังคลาสที่เหมาะสมและไม่ต้องกังวลกับ wrapper
tvanfosson

5
สำหรับการใช้งานในบ้านฉันเริ่มสร้างตัวแปร 'X' ของคลาสแบบสแตติกและโครงสร้างเพื่อเพิ่มส่วนขยายที่กำหนดเอง: 'ConsoleX' มีวิธีแบบคงที่ใหม่สำหรับ 'คอนโซล', 'MathX' มีวิธีแบบคงที่ใหม่สำหรับ 'คณิตศาสตร์', 'ColorX' ขยายวิธีการ 'สี' ฯลฯ ไม่เหมือนกัน แต่จำและค้นพบได้ง่ายใน IntelliSense
user1689175

1
@ Xtro ฉันเห็นด้วยว่ามันแย่มาก แต่ไม่แย่ไปกว่าการไม่สามารถใช้การทดสอบสองครั้งในที่ของมันหรือแย่กว่านั้นคือยอมแพ้ในการทดสอบโค้ดของคุณเพราะคลาสแบบคงที่ทำให้มันยากมาก ไมโครซอฟท์ดูเหมือนจะเห็นด้วยกับฉันเพราะมันเป็นเหตุผลที่พวกเขาแนะนำคลาส HttpContextWrapper / HttpContextBase เพื่อหลีกเลี่ยง HttpContext.Current ในปัจจุบันสำหรับ MVC
tvanfosson

91

คุณสามารถเพิ่มส่วนขยายแบบคงที่ให้กับคลาสใน C # ได้หรือไม่? ไม่ แต่คุณสามารถทำได้:

public static class Extensions
{
    public static T Create<T>(this T @this)
        where T : class, new()
    {
        return Utility<T>.Create();
    }
}

public static class Utility<T>
    where T : class, new()
{
    static Utility()
    {
        Create = Expression.Lambda<Func<T>>(Expression.New(typeof(T).GetConstructor(Type.EmptyTypes))).Compile();
    }
    public static Func<T> Create { get; private set; }
}

นี่คือวิธีการทำงาน ในขณะที่คุณไม่สามารถเขียนวิธีการขยายแบบคงที่ในทางเทคนิค แต่โค้ดนี้ใช้ช่องโหว่ในวิธีการขยาย ช่องโหว่นั้นเป็นสิ่งที่คุณสามารถเรียกใช้วิธีการส่วนขยายบนวัตถุ null โดยไม่ได้รับข้อยกเว้น null (ยกเว้นกรณีที่คุณเข้าถึงสิ่งใดผ่านทาง @this)

ดังนั้นนี่คือวิธีที่คุณจะใช้สิ่งนี้:

    var ds1 = (null as DataSet).Create(); // as oppose to DataSet.Create()
    // or
    DataSet ds2 = null;
    ds2 = ds2.Create();

    // using some of the techniques above you could have this:
    (null as Console).WriteBlueLine(...); // as oppose to Console.WriteBlueLine(...)

ตอนนี้ทำไมฉันถึงเลือกโทร constructor เริ่มต้นเป็นตัวอย่างและและทำไมฉันไม่ส่งคืน T () ใหม่ในตัวอย่างโค้ดแรกโดยไม่ทำขยะนิพจน์ทั้งหมด ดีวันนี้วันโชคดีของคุณเพราะคุณได้รับ 2fer ดังที่ผู้พัฒนา. NET ขั้นสูงรู้ว่า T () ใหม่จะช้าเพราะสร้างการเรียกไปยัง System.Activator ซึ่งใช้การสะท้อนเพื่อรับตัวสร้างเริ่มต้นก่อนที่จะเรียกมัน คุณบ้า Microsoft! อย่างไรก็ตามรหัสของฉันเรียกใช้ตัวสร้างเริ่มต้นของวัตถุโดยตรง

ส่วนขยายคงที่จะดีกว่านี้ แต่เวลาหมดหวังที่จะเรียกใช้มาตรการที่หมดหวัง


2
ผมคิดว่าสำหรับชุดข้อมูลเคล็ดลับนี้จะทำงาน แต่ผมสงสัยว่ามันทำงานสำหรับการเรียนเป็นคอนโซลคอนโซลระดับคงที่ประเภทคงไม่สามารถนำมาใช้เป็นข้อโต้แย้ง :)
ThomasBecker

ใช่ฉันจะพูดในสิ่งเดียวกัน นี่คือวิธีการขยายแบบหลอกที่ใช้กับคลาสที่ไม่คงที่ OP เป็นวิธีการขยายในระดับคงที่
Mark A. Donohoe

2
มันดีกว่าและง่ายกว่าที่จะมีการตั้งชื่อแบบแผนสำหรับวิธีการเช่นXConsoleนี้ConsoleHelperเป็นต้น
Alex Zhukovskiy

9
นี่เป็นเคล็ดลับที่น่าสนใจ แต่ผลลัพธ์ก็ส่งกลิ่น คุณสร้างวัตถุว่างเปล่าจากนั้นปรากฏว่าเรียกใช้วิธีการนั้นแม้ว่าจะมีการบอกเป็นเวลาหลายปีว่า "การเรียกใช้วิธีการบนวัตถุ null ทำให้เกิดข้อยกเว้น" มันใช้งานได้ แต่ .. ugh ... สับสนกับทุกคนที่ดูแลในภายหลัง ฉันจะไม่ลงคะแนนเพราะคุณได้เพิ่มกลุ่มของข้อมูลที่เป็นไปได้ แต่ฉันหวังเป็นอย่างยิ่งว่าจะไม่มีใครใช้เทคนิคนี้ !! ร้องเรียนเพิ่มเติม: ไม่ผ่านหนึ่งของเหล่านี้ไปใช้วิธีการและคาดว่าจะได้รับ subclassing OO: วิธีการที่เรียกว่าจะเป็นประเภทของการประกาศพารามิเตอร์ได้พิมพ์ของพารามิเตอร์ผ่าน
ToolmakerSteve

5
นี่เป็นเรื่องยุ่งยาก แต่ฉันชอบมัน ทางเลือกหนึ่งที่(null as DataSet).Create();อาจเป็นdefault(DataSet).Create();ไปได้
Bagerfahrer

54

มันเป็นไปไม่ได้.

และใช่ฉันคิดว่า MS ทำผิดพลาดที่นี่

การตัดสินใจของพวกเขาไม่สมเหตุสมผลและบังคับให้โปรแกรมเมอร์เขียน (ตามที่อธิบายไว้ข้างต้น) คลาส wrapper ที่ไม่มีจุดหมาย

นี่คือตัวอย่างที่ดี: การพยายามที่จะขยายคง MS หน่วยทดสอบระดับยืนยัน: ฉันต้องการมากขึ้น assert AreEqual(x1,x2)วิธี

วิธีเดียวในการทำเช่นนี้คือชี้ไปที่คลาสที่ต่างกันหรือเขียน wrapper ประมาณ 100s ของวิธี Assert ที่แตกต่างกัน ทำไม!?

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


20
ฉันพยายามขยาย MS Unit Test Class Assert เพื่อเพิ่ม Assert.Throws และ Assert.DoesNotThrow และประสบปัญหาเดียวกัน
Stefano Ricciardi

3
ใช่ฉันด้วย :( ฉันคิดว่าฉันสามารถทำได้Assert.Throwsกับคำตอบstackoverflow.com/questions/113395/…
CallMeLaNN

27

ฉันสะดุดในหัวข้อนี้ในขณะที่พยายามค้นหาคำตอบของคำถามเดียวกันที่ OP มี ฉันไม่พบคำตอบที่ฉันต้องการ แต่ท้ายที่สุดฉันก็ทำได้

public static class MyConsole
{
    public static void WriteLine(this ConsoleColor Color, string Text)
    {
        Console.ForegroundColor = Color;
        Console.WriteLine(Text);   
    }
}

และฉันใช้มันเช่นนี้

ConsoleColor.Cyan.WriteLine("voilà");

19

บางทีคุณสามารถเพิ่มคลาสแบบคงที่ด้วยเนมสเปซที่กำหนดเองและชื่อคลาสเดียวกัน:

using CLRConsole = System.Console;

namespace ExtensionMethodsDemo
{
    public static class Console
    {
        public static void WriteLine(string value)
        {
            CLRConsole.WriteLine(value);
        }

        public static void WriteBlueLine(string value)
        {
            System.ConsoleColor currentColor = CLRConsole.ForegroundColor;

            CLRConsole.ForegroundColor = System.ConsoleColor.Blue;
            CLRConsole.WriteLine(value);

            CLRConsole.ForegroundColor = currentColor;
        }

        public static System.ConsoleKeyInfo ReadKey(bool intercept)
        {
            return CLRConsole.ReadKey(intercept);
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                Console.WriteBlueLine("This text is blue");   
            }
            catch (System.Exception ex)
            {
                Console.WriteLine(ex.Message);
                Console.WriteLine(ex.StackTrace);
            }

            Console.WriteLine("Press any key to continue...");
            Console.ReadKey(true);
        }
    }
}

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


11

Nope คำจำกัดความวิธีการส่วนขยายต้องการอินสแตนซ์ของประเภทที่คุณกำลังขยาย มันโชคร้าย ฉันไม่แน่ใจว่าทำไมมันถึงต้องการ ...


4
มันเป็นเพราะมีการใช้วิธีการขยายเพื่อขยายตัวอย่างของวัตถุ หากพวกเขาไม่ทำอย่างนั้นพวกเขาก็คงจะเป็นวิธีคงที่ปกติ
Derek Ekins

31
มันคงจะดีถ้าทำทั้งสองอย่างใช่มั้ย

7

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

Mr. Obnoxious wrote: "เมื่อใดก็ตามที่นักพัฒนา. NET รู้ขั้นสูงใหม่ T () จะช้าเพราะมันสร้างการเรียกไปที่ System.Activator ซึ่งใช้การสะท้อนเพื่อรับตัวสร้างเริ่มต้นก่อนที่จะเรียกมัน"

ใหม่ () ถูกคอมไพล์ไปยังคำสั่ง IL "newobj" ถ้ารู้ชนิดเวลาการคอมไพล์ Newobj ใช้ตัวสร้างสำหรับการเรียกใช้โดยตรง โทรไปที่ System.Activator.CreateInstance () รวบรวมคำสั่ง IL "call" เพื่อเรียกใช้ System.Activator.CreateInstance () ใหม่ () เมื่อใช้กับประเภททั่วไปจะส่งผลให้มีการเรียกไปที่ System.Activator.CreateInstance () โพสต์โดย Mr. Obnoxious ไม่ชัดเจนในจุดนี้ ... และก็น่ารังเกียจ

รหัสนี้:

System.Collections.ArrayList _al = new System.Collections.ArrayList();
System.Collections.ArrayList _al2 = (System.Collections.ArrayList)System.Activator.CreateInstance(typeof(System.Collections.ArrayList));

ผลิต IL นี้:

  .locals init ([0] class [mscorlib]System.Collections.ArrayList _al,
           [1] class [mscorlib]System.Collections.ArrayList _al2)
  IL_0001:  newobj     instance void [mscorlib]System.Collections.ArrayList::.ctor()
  IL_0006:  stloc.0
  IL_0007:  ldtoken    [mscorlib]System.Collections.ArrayList
  IL_000c:  call       class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
  IL_0011:  call       object [mscorlib]System.Activator::CreateInstance(class [mscorlib]System.Type)
  IL_0016:  castclass  [mscorlib]System.Collections.ArrayList
  IL_001b:  stloc.1

5

คุณไม่สามารถเพิ่มวิธีการคงที่ให้กับประเภท คุณสามารถเพิ่ม (pseudo-) วิธีการอินสแตนซ์ให้กับอินสแตนซ์ของประเภทได้

จุดของการthisปรับปรุงคือการบอกให้คอมไพเลอร์ C # ผ่านอินสแตนซ์ที่ด้านซ้ายของ.พารามิเตอร์แรกของวิธีการคงที่ / ส่วนขยาย

ในกรณีของการเพิ่มวิธีการคงที่ให้กับประเภทไม่มีอินสแตนซ์ที่จะผ่านสำหรับพารามิเตอร์แรก


4

ฉันพยายามทำสิ่งนี้ด้วย System.Environment ย้อนกลับไปเมื่อฉันเรียนรู้วิธีการขยายและไม่ประสบความสำเร็จ เหตุผลก็คืออย่างที่คนอื่นพูดถึงเพราะวิธีการขยายต้องมีตัวอย่างของชั้นเรียน


3

มันเป็นไปไม่ได้ที่จะเขียนวิธีการขยายอย่างไรก็ตามมันเป็นไปได้ที่จะเลียนแบบพฤติกรรมที่คุณขอ

using FooConsole = System.Console;

public static class Console
{
    public static void WriteBlueLine(string text)
    {
        FooConsole.ForegroundColor = ConsoleColor.Blue;
        FooConsole.WriteLine(text);
        FooConsole.ResetColor();
    }
}

สิ่งนี้จะอนุญาตให้คุณเรียกใช้ Console.WriteBlueLine (fooText) ในคลาสอื่น ๆ ถ้าคลาสอื่นต้องการเข้าถึงฟังก์ชันคงที่อื่น ๆ ของ Console พวกเขาจะต้องอ้างอิงอย่างชัดเจนผ่านเนมสเปซของพวกเขา

คุณสามารถเพิ่มวิธีการทั้งหมดในการเปลี่ยนคลาสได้ตลอดเวลาหากคุณต้องการที่จะมีทั้งหมดในที่เดียว

ดังนั้นคุณจะมีสิ่งที่ชอบ

using FooConsole = System.Console;

public static class Console
{
    public static void WriteBlueLine(string text)
    {
        FooConsole.ForegroundColor = ConsoleColor.Blue;
        FooConsole.WriteLine(text);
        FooConsole.ResetColor();
    }
    public static void WriteLine(string text)
    {
        FooConsole.WriteLine(text);
    }
...etc.
}

สิ่งนี้จะแสดงพฤติกรรมที่คุณต้องการ

* หมายเหตุจะต้องมีการเพิ่มคอนโซลผ่านเนมสเปซที่คุณวางไว้


1

ใช่ในความหมายที่ จำกัด

public class DataSet : System.Data.DataSet
{
    public static void SpecialMethod() { }
}

สิ่งนี้ใช้ได้ แต่ Console ไม่ได้เพราะเป็นแบบคงที่

public static class Console
{       
    public static void WriteLine(String x)
    { System.Console.WriteLine(x); }

    public static void WriteBlueLine(String x)
    {
        System.Console.ForegroundColor = ConsoleColor.Blue;
        System.Console.Write(.x);           
    }
}

สิ่งนี้ใช้ได้เพราะตราบใดที่มันไม่อยู่ในเนมสเปซเดียวกัน ปัญหาคือคุณต้องเขียนวิธีคงที่พร็อกซีสำหรับทุกวิธีที่ System.Console มี ไม่จำเป็นต้องเป็นเรื่องเลวร้ายเพราะคุณสามารถเพิ่มสิ่งนี้:

    public static void WriteLine(String x)
    { System.Console.WriteLine(x.Replace("Fck","****")); }

หรือ

 public static void WriteLine(String x)
    {
        System.Console.ForegroundColor = ConsoleColor.Blue;
        System.Console.WriteLine(x); 
    }

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


โชคไม่ดีที่วิธีการใช้ลูกหลานจะไม่ทำงานเมื่อคลาสฐานถูกปิดผนึก (เช่นในไลบรารีคลาส NET.)
George Birbilis

1

ต่อไปนี้ถูกปฏิเสธเป็นการแก้ไขคำตอบของ tvanfosson ฉันถูกขอให้บริจาคมันเป็นคำตอบของฉันเอง ฉันใช้คำแนะนำของเขาและเสร็จสิ้นการใช้ConfigurationManagerกระดาษห่อ ตามหลักการแล้วฉันเพียงแค่...ตอบคำถามของ tvanfosson

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

public static class ConfigurationManagerWrapper
{
    public static NameValueCollection AppSettings
    {
        get { return ConfigurationManager.AppSettings; }
    }

    public static ConnectionStringSettingsCollection ConnectionStrings
    {
        get { return ConfigurationManager.ConnectionStrings; }
    }

    public static object GetSection(string sectionName)
    {
        return ConfigurationManager.GetSection(sectionName);
    }

    public static Configuration OpenExeConfiguration(string exePath)
    {
        return ConfigurationManager.OpenExeConfiguration(exePath);
    }

    public static Configuration OpenMachineConfiguration()
    {
        return ConfigurationManager.OpenMachineConfiguration();
    }

    public static Configuration OpenMappedExeConfiguration(ExeConfigurationFileMap fileMap, ConfigurationUserLevel userLevel)
    {
        return ConfigurationManager.OpenMappedExeConfiguration(fileMap, userLevel);
    }

    public static Configuration OpenMappedMachineConfiguration(ConfigurationFileMap fileMap)
    {
        return ConfigurationManager.OpenMappedMachineConfiguration(fileMap);
    }

    public static void RefreshSection(string sectionName)
    {
        ConfigurationManager.RefreshSection(sectionName);
    }
}

0

คุณสามารถใช้เพี้ยนเป็นโมฆะเพื่อให้ทำงานได้

public static class YoutTypeExtensionExample
{
    public static void Example()
    {
        ((YourType)null).ExtensionMethod();
    }
}

ส่วนขยาย:

public static class YourTypeExtension
{
    public static void ExtensionMethod(this YourType x) { }
}

YourType:

public class YourType { }

-4

คุณสามารถทำได้ถ้าคุณยินดีที่จะ "frig" เล็กน้อยโดยการทำให้ตัวแปรของคลาสคงที่และกำหนดให้เป็นโมฆะ อย่างไรก็ตามวิธีนี้จะไม่สามารถใช้ได้กับการโทรคงที่ในชั้นเรียนดังนั้นไม่แน่ใจว่าจะใช้งานได้เท่าไร:

Console myConsole = null;
myConsole.WriteBlueLine("my blue line");

public static class Helpers {
    public static void WriteBlueLine(this Console c, string text)
    {
        Console.ForegroundColor = ConsoleColor.Blue;
        Console.WriteLine(text);
        Console.ResetColor();
    }
}

นี่คือสิ่งที่ฉันทำ ชั้นเรียนของฉันชื่อ MyTrace :)
Gishu

เคล็ดลับที่มีประโยชน์ มีกลิ่นโค้ดนิดหน่อย แต่ฉันคิดว่าเราสามารถซ่อนวัตถุว่างไว้ในคลาสฐานหรืออะไรบางอย่าง ขอบคุณ
Tom Deloford

1
ฉันไม่สามารถคอมไพล์รหัสนี้ได้ ข้อผิดพลาด 'System.Console': ไม่สามารถใช้ประเภทคงที่เป็นพารามิเตอร์ได้
kuncevic.dev

ใช่สิ่งนี้ไม่สามารถทำได้ ประณามฉันคิดว่าคุณกำลังเข้าสู่บางสิ่งที่นั่น! ประเภทคงที่ไม่สามารถส่งผ่านเป็นพารามิเตอร์ในวิธีการซึ่งทำให้รู้สึกฉันคิดว่า เราแค่หวังว่า MS จะเห็นไม้จากต้นไม้ในต้นนี้และเปลี่ยนมัน
Tom Deloford

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