2017-01-03 52 views
1

我有接口,定義值和一些操作:如何使用泛型編寫通用操縱器?

public interface IValue<T> 
{ 
    T Value { get; } 

    void InteractionA(IValue<T> target); 
    void InteractionB(IValue<T> target); 
    bool Check(IValue<T> target); 
} 

然後,我基於該接口

public class DoubleValue : IValue<double> 
{ 
    public double Value { get; private set; } 

    public bool Check(IValue<double> target) 
    { 
     // ... 
     return false; 
    } 

    public void InteractionA(IValue<double> target) 
    { 
     // ... 
    } 

    public void InteractionB(IValue<double> target) 
    { 
     // ... 
    } 
} 

現在我想做出對池操作的值,並使用泛型通用機械手在實現類(所以我只寫一次)。由於我想在將來使用這個類的方式,它不能被聲明爲靜態的。將泛型類型移入方法也沒有任何好處。 最接近我能得到的是:

public class ValueManipulator<T> 
{ 
    public IEnumerable<IValue<T>> Pool { get; private set; } 

    public ValueManipulator(IEnumerable<IValue<T>> pool) 
    { 
     Pool = pool; 
    } 

    public void ManipulateA() 
    { 
     foreach (int i in Enumerable.Range(0, Pool.Count())) 
     { 
      IValue<T> firstValue = Pool.ElementAt(i); 

      foreach (IValue<T> secondValue in Pool.Skip(i)) 
      { 
       if (firstValue.Check(secondValue)) 
        firstValue.InteractionA(secondValue); 

       else 
        firstValue.InteractionB(secondValue); 
      } 
     } 
    } 

    public void ManipulateB() 
    { 
     // ... 
    } 
} 

與此ValueManipulator類主要問題是,我需要知道iValue的1噸的doubleValue使用(在這種情況下,雙)。所以它看起來像這樣:

static void Main(string[] args) 
{ 
    ValueManipulator<double> doubleManipulator = new ValueManipulator<double>(); 
    doubleManipulator.Manipulate(ProvideDoubles()); 
} 

private static IEnumerable<DoubleValue> ProvideDoubles() 
{ 
    yield return new DoubleValue(); 
    yield return new DoubleValue(); 
    yield return new DoubleValue(); 
} 

如何使ValueManipulator因此用戶並不需要知道價值實現是使用什麼類型的?

+1

你可以簡化你的循環'int i = 1; foreach(var首先在池中){foreach(var second in pool.Skip(i)){....} i ++;}' – juharr

回答

2

好吧,如果您的ValueManipulator<T>沒有狀態,根據您的代碼片段看起來是您的情況,那麼只需使方法爲泛型而不是類,這樣您就可以利用類型推斷。

public class ValueManipulator 
{ 
    public void Manipulate<T>(IEnumerable<IValue<T>> pool) 
    { 
     foreach (int i in Enumerable.Range(0, pool.Count())) 
     { 
      IValue<T> firstValue = pool.ElementAt(i); 

      foreach (IValue<T> secondValue in pool.Skip(i)) 
      { 
       if (firstValue.Check(secondValue)) 
        firstValue.InteractionA(secondValue); 

       else 
        firstValue.InteractionB(secondValue); 
      } 
     } 
    } 
} 

現在,你可以簡單地做:

ValueManipulator myManipulator = new ValueManipulator(); 
myManipulator.Manipulate(ProvideDoubles()); //type inference will figure out T is double 

如果這是一個有效的解決方案,然後考慮做ValueManipulator靜態類:

ValueManipulator.Manipulate(ProvideDoubles()); 

P.D.請遵照評論中的建議,並將ValueType更改爲其他較不混淆的名稱。

UPDATE您最新的編輯你的問題,其中明確聲明ValueManipulator<T>確實有狀態後,溶液似乎是實現一個靜態工廠類:

public static class ValueManipulator 
{ 
    public static ValueManipulator<T> Create<T>(IEnumerable<IValue<T>> pool) 
     => new ValueManipulator<T>(pool); 
} 

public class ValueManipulator<T> { ... } 

你又再次讓類型推理完成其工作:

var doubleManipulator = ValueManipulator.Create(ProvideDoubles()); 
+0

你是對的,它看起來像ValueManipulator沒有狀態,但它過於簡化的方法即時通訊正在工作(並有實例要求)。生病更新我的問題。 – Creo

+0

@Creo見編輯。 – InBetween

+0

這確實是一個解決方案。 – Creo