English 中文(简体)
通用接口和多变
原标题:generic interfaces and polymorphism

我有以下法典:

public abstract class Operand<T>
{
    public T Value { get; protected set; }

    public bool IsEmpty { get; protected set; }

    public override string ToString()
    {
        return IsEmpty ? Value.ToString() : string.Empty;
    }
}
public class DoubleOperand : Operand<Double> {}

public interface IOperandFactory<T>
    {
        Operand<T> CreateEmptyOperand();
        Operand<T> CreateOperand(T value);
    }

public class DoubleFactory: IOperandFactory<double>
{
    public Operand<Double> CreateEmptyOperand()
    {
        //implementation
    }

    public Operand<Double> CreateOperand(double value)
    {
        //implementation
    }
}

I simlified code to just show the structure. Now I need associationDictionary that will return IOperandFactory for required Type: Something like this:

var factoryDict = 
new Dictionary<Type, IOperandFactory<>>() { { typeof(double), new DoubleFactory() } };

如果有可能,你能否帮助我实现这一目标?

最佳回答

为此,您需要有一种非遗传的界面(通常除了通用接口外),即一种非遗传性的<代码>Operand,其编号为Operand<T> : (也可作为接口)和非遗传性<代码>IOperandFactory Factory<T> :IOperandFactory 。 唯一的其他选择是储存<代码>Dictionary<Type, Object>,必要时配电机。

Here s the non-generic approach:

using System.Collections.Generic;
using System;
public interface IOperand
{
    object Value { get; }
    bool IsEmpty { get; }
}
public abstract class Operand<T> : IOperand
{
    public T Value { get; protected set; }
    object IOperand.Value { get { return Value; } }
    public bool IsEmpty { get; protected set; }
    public override string ToString()
    {
        return IsEmpty ? Value.ToString() : string.Empty;
    }
}
public class DoubleOperand : Operand<double> { }

public interface IOperandFactory
{
    IOperand CreateEmptyOperand();
    IOperand CreateOperand(object value);
}
public interface IOperandFactory<T> : IOperandFactory
{
    new Operand<T> CreateEmptyOperand();
    Operand<T> CreateOperand(T value);
}

public class DoubleFactory : IOperandFactory<double>
{
    public Operand<double> CreateEmptyOperand()
    {
        throw new NotImplementedException();
    }
    IOperand IOperandFactory.CreateEmptyOperand() {
        return CreateEmptyOperand();
    }

    IOperand IOperandFactory.CreateOperand(object value) {
        return CreateOperand((double)value);
    }
    public Operand<double> CreateOperand(double value)
    {
        throw new NotImplementedException();
    }
}

static class Program
{
    static void Main()
    {
        var factoryDict = new Dictionary<Type, IOperandFactory> {
          {typeof (double), new DoubleFactory()}
        };
    }
}
问题回答

If I understand correctly, you are trying to store a collection of generic types, where the generic type parameters may vary. If this is the case, it is not directly possible, as the following example illustrates:

// You have lists of different types:
List<double> doubleCollection = new List<double>();
List<string> stringCollection = new List<string>();

// Now to store generically:
var collection = new List<List< /* ... Which type parameter to use? ... */ >>();

这里可以明显看出的是,不可能减少哪类参数需要使用。 相反(关于你的榜样),你可能希望这样做:

public interface IOperand
{
}

public interface IOperand<T>
{
}

public interface IOperandFactory
{
    IOperand CreateEmptyOperand();
    IOperand CreateOperand(object value);
}

public interface IOperandFactory<T> : IOperandFactory
{
    new IOperand<T> CreateEmptyOperand();
    IOperand<T> CreateOperand(T value);
}

public class DoubleFactory : IOperandFactory<double>
{
    public IOperand<double> CreateEmptyOperand()
    {
        throw new NotImplementedException();
    }

    public IOperand<double> CreateOperand(double value)
    {
        throw new NotImplementedException();
    }

    IOperand IOperandFactory.CreateEmptyOperand()
    {
        throw new NotImplementedException();
    }

    public IOperand CreateOperand(object value)
    {
        throw new NotImplementedException();
    }
}

public class SomeContainer
{
    public SomeContainer()
    {
        var factoryDict = new Dictionary<Type, IOperandFactory>()
        {
            { typeof(double), (IOperandFactory)new DoubleFactory() }
        };
    }
}

这可能不是解决办法的最棘手问题,但这将使你能够在同一收藏中储存不同的通用类型。 然而,与此相关的一个问题是,获得这种收集的打电话者需要知道什么类型的东西。 例如:

// ... Inside SomeContainer ...
public IOperandFactory<T> GetFactory<T>()
{
    return (IOperandFactory<T>)factoryDict[typeof(T)];
}

因此,你可以找到<代码>。 2. 两用产品:

IOperandFactory<double> doubleFactory = mSomeContainerInstance.GetFactory<double>();
IOperand<double> emptyOperand = doubleFactory.CreateEmptyOperand();
IOperand<double> filledOperand = doubleFactory.CreateOperand(1.0d);




相关问题
Anyone feel like passing it forward?

I m the only developer in my company, and am getting along well as an autodidact, but I know I m missing out on the education one gets from working with and having code reviewed by more senior devs. ...

NSArray s, Primitive types and Boxing Oh My!

I m pretty new to the Objective-C world and I have a long history with .net/C# so naturally I m inclined to use my C# wits. Now here s the question: I feel really inclined to create some type of ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

How to Use Ghostscript DLL to convert PDF to PDF/A

How to user GhostScript DLL to convert PDF to PDF/A. I know I kind of have to call the exported function of gsdll32.dll whose name is gsapi_init_with_args, but how do i pass the right arguments? BTW, ...

Linqy no matchy

Maybe it s something I m doing wrong. I m just learning Linq because I m bored. And so far so good. I made a little program and it basically just outputs all matches (foreach) into a label control. ...

热门标签