簡體   English   中英

C#泛型和方法

[英]C# Generic and method

如何選擇好的方法(在下面的示例中,我將顯示2種無效的方法)。 我使用的不是帶有IF和IS的Object類型的變量來完成這項工作,但我試圖避免使用Object和裝箱/拆箱。 所以我以為Generic可以勝任這項工作,但我被困在這里。

這是一小段代碼,闡明了我的問題:

class Program
{
    static void Main(string[] args)
    {
        Parser p = new Parser();
        ObjectType1 o1 = new ObjectType1();
        p.execute(o1);
        Console.Read();
    }
}

class Parser
{
    public T execute<T>(T obj)
    {
        /*
        if (obj is ObjectType1)
            this.action((ObjectType1)obj);
        else if (obj is ObjectType2)
            this.action((ObjectType2)obj);
        */
        this.action(obj);
        return obj;
    }

    private void action(ObjectType1 objectType1)
    {
        Console.WriteLine("1");
    }

    private void action(ObjectType2 objectType2)
    {
        Console.WriteLine("2");
    }
}


class ObjectType1
{
}

class ObjectType2
{
}

更新資料

我不要界面和類。 抱歉。 我知道這不是問題的目的。

使用(ObjectType)obj進行投射不起作用,但是如果您這樣做:

        if (obj is ObjectType1)
            this.action(obj as ObjectType1);
        else if (obj is ObjectType2)
            this.action(obj as ObjectType1);

它有效...為什么?

而且...我無法為所有類型的execute方法重載,因為該方法來自Interface。 這就是為什么需要從此方法調用所有對象的原因。

不,你不能這樣做。 泛型不像C ++模板那樣工作-泛型方法僅編譯一次。 編譯器可用於重載解析的唯一信息是它在通用方法中了解的信息,而不管使用什么代碼。

作為顯示此示例的示例,以下是一些代碼,可能無法按預期運行:

using System;

class Test
{    
    static void Main()
    {
        string x = "hello";
        string y = string.Copy(x);

        Console.WriteLine(x==y); // Overload used
        Compare(x, y);
    }

    static void Compare<T>(T x, T y) where T : class
    {
        Console.WriteLine(x == y); // Reference comparison
    }
}

在不進一步了解您想做什么的情況下,很難說出最佳的前進方法。

您考慮過接口嗎?

interface IAction
{
   void action();
}

class ObjectType1 : IAction
{
   void action() {
      Console.WriteLine("1");
   }
}

class ObjectType2 : IAction
{
    void action() {
      Console.WriteLine("2");
    }
}

class Parser
{
   public IAction execute(IAction obj)
   {
      obj.action();
      return obj;
   }
}

由OP編輯:

此解決方案將需要更改所有業務邏輯對象以具有此接口。 在我看來,這確實不是要做的事情。 而且,在其他情況下,我總是更喜歡干凈的BusinessObject,而該Object的Interface與業務無關。 在我的問題中,我想要一個與Generic / Object / Delegate方法更相關的解決方案來實現。 謝謝你 此答案將不被接受。

我沒有嘗試過,但是您可以這樣做嗎?

 
 
 
  
  public T execute<T>(T obj) { this.action((T)obj); return obj; }
 
  

(根據評論,不起作用)

要么

public T execute<T>(T obj)
{
    this.action(obj as T);
    return obj;
}

(根據評論,作品)

解析器類具有許多私有方法,這些私有方法由execute方法根據對象類型調用。 它需要重定向到好的方法。

編譯器將為您完成這項工作。 只需使用重載即可。

class Parser
{
    public ObjectType1 action(ObjectType1 objectType1)
    {
        Console.WriteLine("1");
        return objectType1;
    }
    public ObjectType2 action(ObjectType2 objectType2)
    {
        Console.WriteLine("2");
        return objectType2;
    }
}

class ObjectType1 { }
struct ObjectType2 { }

然后,調用:

Parser p = new Parser();
p.action(new ObjectType1());
p.action(new ObjectType2());

沒有裝箱/拆箱,並且調用了適當的方法。

我知道您擔心裝箱/拆箱,因此此處可能涉及ValueType。

public T execute<T>(T obj)   
{        
    this.action(obj);
    return obj;
}

假設該操作正在修改obj,還假設該修改對調用方很重要 (這就是為什么要將值返回給調用方的原因)。 該代碼有一個討厭的傳遞值缺陷。

考慮以下代碼:

    public int execute(int obj)   
    {        
        this.action(obj);
        return obj;
    }

    public void action(int obj)
    {
        obj = obj + 1;
    }

以這種方式調用。

int x = p.execute(1);

x是1,不是2。

IIRC,您可以使用“ where”子句來允許

public T execute<T>(T obj) where : /* somthing */
{
}

我總是不得不向Google透露自己的看法,因此我將其保留下來。

編輯:閱讀一些評論。 我不建議調用特定於類型的代碼。 而是將代碼放在虛函數中並調用它。 呼叫簽名可能會很長,但這就是自動完成的目的。

Koodos到joshua.ewer查找手冊頁

泛型發生在編譯時。 當您希望同一代碼應用於不同類型時,最好使用此方法。 它不是動態的,因此不會幫助您根據輸入類型在方法之間進行切換。

像David B的回復一樣,重載解析也可以,但是在編譯時也會發生。

更新中的代碼執行相同的操作。 它進行轉換(在仔細檢查類型之后),然后使用重載來解析該方法。

我覺得您想根據運行時輸入切換方法。

如果使用反射,則可以得到更動態的行為。

        public object execute(object obj) 
        {
            MethodInfo m = typeof(Parser).GetMethod(
                "action", 
                BindingFlags.Instance | BindingFlags.NonPublic, 
                null, 
                new Type[] { obj.GetType() }, 
                null);
            m.Invoke(this, new object[] { obj });
            return obj; 
        } 

它可能有點脆弱,但是在示例中可以使用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM