在C#中使用泛型和接口时如何避免强制转换

时间:2016-03-10 19:13:59

标签: c# generics interface

在以下代码中,IPointIPointGroup是现有接口的缩写版本,用于定义如何在大型应用程序的许多部分之间共享数据。

RefPoint<T>PointGroup<T>的缩写通用实现用于处理大量点的新子系统,因此需要考虑最小化使用所需的重复和转换。分。

在代码的底部,说明了两个问题:

  1. 要通过共同的界面处理所有要点,我采取的方法要求每个点都被投射
  2. 我无法通过IPointGroup<T>通用界面投射或以其他方式使用积分。
  3. 我很欣赏我所采取的方法的建议/改进。我对C#泛型来说很陌生,所以我可能会遗漏一些明显的东西。

    using System;
    
    namespace Generic
    {
    
    public interface IPoint { }
    public interface IPointGroup
    {  void Add( IPoint x );
    }
    
    public interface IPointGroup<T> where T : IPoint
    {  void Add( T x );
    }
    
    public class RefPoint<T> : IPoint
    {
        public int X, Y;
        T _refersTo;
    
        public RefPoint( int x, int y, T refersTo )
        {
            X = x;
            Y = y;
            _refersTo = refersTo;
        }
        public T refersTo()
        {  return _refersTo;
        }
    }
    
    public class PointGroup<T> : IPointGroup where T : IPoint
    {
        internal void Add( T y )
        {
            Console.WriteLine("In Add( T y )");
        }
        public void Add( IPoint x )
        {
            Console.WriteLine("In Add(IA x)");
            Add((T)x);
        }
    }
    
    public class Swerve : IPoint { }
    public class HardBrake : IPoint { }
    public class StopSign { };
    
    class Program
    {
        static void Main( string[] args )
        {
            PointGroup<Swerve> swerves = new PointGroup<Swerve>();
            PointGroup<HardBrake> hardBrakes = new PointGroup<HardBrake>();
            PointGroup<RefPoint<StopSign>> stopSigns = new PointGroup<RefPoint<StopSign>>();
            PointGroup<IPoint> all = new PointGroup<IPoint>();
    
            Swerve s = new Swerve();
            swerves.Add(s);
    
            HardBrake h = new HardBrake();
            hardBrakes.Add(h);
    
            StopSign ss = new StopSign();
            RefPoint<StopSign> ss_ref = new RefPoint<StopSign>(1,1,ss);
            stopSigns.Add(ss_ref);
    
            // Problem #1: Each element is cast
            all.Add(s);
            all.Add(h);
            all.Add(ss_ref);
    
            // Problem #2: Can't cast as follows
            // IPointGroup<Swerve> iSwerves = (IPointGroup<Swerve>)swerves;
            // IPointGroup<HardBrake> iHardBrakes = (IPointGroup<HardBrake>)hardBrakes;
            // IPointGroup<RefPoint<StopSign>> iStopSigns = (IPointGroup<RefPoint<StopSign>>) stopSigns;
            // IPointGroup<IPoint> iAll = (IPointGroup<IPoint>)all;
        }
    }
    
    }
    

1 个答案:

答案 0 :(得分:1)

在此实施IPointGroup

public class PointGroup<T> : IPointGroup where T : IPoint

虽然你可能意味着IPointGroup<T>

public class PointGroup<T> : IPointGroup<T> where T : IPoint

此外,IPointGroupIPointGroup<T>无论如何都与您的设计无关。当需要非泛型和通用版本的接口时,通用方法是通用方法继承非泛型方法;因此:

public interface IPointGroup<T> : IPointGroup where T : IPoint

另外,为了从通用版主要中受益,请考虑明确地实现非通用版本,如下所示:

public class PointGroup<T> : IPointGroup<T> where T : IPoint
{
    // implicit implementation of IPointGroup<T>.Add(T)
    public void Add(T y) { … }

    // explicit implementation of IPointGroup.Add(IPoint)
    void IPointGroup.Add(IPoint x)
    {
        Add((T)x);
    }
}