实现多参数C ++使用策略模式像C#的行为模板 [英] Implementing multiparameter C++ template like behaviour on C# using Policy Pattern

查看:205
本文介绍了实现多参数C ++使用策略模式像C#的行为模板的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想实现一个类似于C ++基于这个答案



这是该模式的一个样本:

 接口ISomePolicy< T,U> ; 
{
无效_doSomething(U U);
}


类MyClass的< T,U计算值:
ISomePolicy< INT,双>中
ISomePolicy< INT,INT>
{

内部温度T myElement {获取;集;}

公共MyClass的(T元){
myElement =元素;
}

无效ISomePolicy< INT,双> ._ DoSomething的(双U)
{
Console.WriteLine(这是INT,双);
}

无效ISomePolicy< INT,INT> ._ DoSomething的(INT U)
{
Console.WriteLine(这是INT,INT);
}

}

静态类MyClassExtension
{

//我想这样做
公众什么静态无效DoSomething的< P,T,U>(该p OTH,U U),其中P:MyClass的< T,U>中ISomePolicy< T,U>
{
oTh._doSomething(U);
}

}



我的预期的行为是这样的:

  MyClass的< INT,双> oClass =新MyClass的< INT,双>(3); 

oClass.doSomething(0.5); //这个工程
oClass.doSomething(1); //这个工程

oClass.doSomething(这应该失败); //休息在编译时

MyClass的<字符串,双> oClass1 =新MyClass的<字符串,双>(sadfsd); //不落实,未能阻止施工。

oClass1.doSomething(0.4); //休息在编译时



但到目前为止,我没有能够使.NET接受<一个HREF =htt​​p://stackoverflow.com/q/36022971/1477064>比参数



少论据通用扩展我可以明确地调用接口,这是可怕的冗长击败这一切的目的

  oClass.doSomething< MyClass的< INT,双>,整型,双>(0.5); 



我想工作,与一个包装周围:

 静态类MyClassExtension {
私有静态无效wrappedDoSomething< P,T,U>(该p OTH,U U)
,其中P:MyClass的<吨,U>中ISomePolicy< T,U>
{
oTh._doSomething(U);
}

公共静态无效DoSomething的< T,U>(这MyClass的< T,U> OTH,U U)

{
超视距。 wrappedDoSomething< MyClass的< T,U>中T,U>(U);
}
}



但包装不能解决这两种类型的包装的函数,具有故障:




错误1类型MyClass的'不能被用作类型参数中的p
泛型类型或方法
'MyClassExtension.wrappedDoSomething(P,U)。有一个从'MyClass的'到
没有
隐式引用转换ISomePolicy




任何见解修复参数问题,或者重新设计这一切是值得赞赏的。






有关背景下,这将被用来包裹I / O的翻译。 T 在我的情况是目标I / O格式, U 通过使用该数据的对象表示我框架。



我知道,这可以通过委托或接口上轻松实现,但客观上,该框架的用户很容易地实例化所需的翻译,以及如果实现。不存在,它可以被平凡加入到一个公共接口






编辑:从内侧另一个解决的通用方法泛型方法/类既不似乎对单工作。


解决方案

想你的代码,但即使是简单的通话没有发挥出来框。主要的问题是MyClass的包含未知元素类型'myEement' - 该类型不能从函数调用的参数推导。但是 - 如果你犯了一个概括和省略对象类型 - 您的样品将在工作开箱方式:

 使用系统; 
使用System.Collections.Generic;

接口ISomePolicy< U>
{
无效_doSomething(U U);
}

公共MyClass类< U> :
ISomePolicy<双>中
ISomePolicy< INT>
{
内部对象myEement {搞定;组; }

公共MyClass的(对象元素)
{
myEement =元素;
}

无效ISomePolicy<双> ._ DoSomething的(双U)
{
Console.WriteLine(这双);
}

无效ISomePolicy< INT> ._ DoSomething的(INT U)
{
Console.WriteLine(这是INT);
}
}

静态类MyClassExtension
{
公共静态无效DoSomething的< P,U>(该p OTH,U U),其中P: ISomePolicy< U>
{
oTh._doSomething(U);
}
}

类节目
{
静态无效的主要()
{
MyClass的<双> oClass =新MyClass的<双>(3);
oClass.doSomething(0.5); //这个工程
oClass.doSomething(1); //这个工程
//oClass.doSomething(\"Will不行);
}
}



什么是高达myEement(或者你可能是指myElement ) - 你可以得到的在运行时,如果需要它的类型

  myElement.GetType(),或者转换为它 - 例如: 
如果(myElement为int)DoSomethingWithInt((INT)myElement);



不过 - 反射总是可能的执行变慢。如果你不打算创建超重型类层次结构与实例数量巨大 - 那么这应该是足以满足您的需求。


I'm trying to implement a c++ like template with C# generics and policy pattern based on this answer

This is a sample of the pattern:

interface ISomePolicy<T,U>
{
    void _doSomething(U u);
}


class MyClass<T,U>:
     ISomePolicy<int, double>,
     ISomePolicy<int, int>
    {

    internal T myElement {get;set;}

    public MyClass(T Element) {
        myElement = Element;
    }

    void ISomePolicy<int, double>._doSomething(double u)
    {
        Console.WriteLine("this is int, double");
    }

    void ISomePolicy<int, int>._doSomething(int u)
    {
        Console.WriteLine("this is int, int");
    }

    }

static class MyClassExtension
{

    //What I want to do
    public static void doSomething<P, T, U>(this P oTh, U u) where P : MyClass<T, U>, ISomePolicy<T, U>
    {
        oTh._doSomething(u);
    }

}

My intended behaviour is like this:

  MyClass<int, double> oClass = new MyClass<int, double>(3);

  oClass.doSomething(0.5); //This works
  oClass.doSomething(1);   //This works

  oClass.doSomething("This should fail"); //Breaks at compile time           

  MyClass<string, double> oClass1 = new MyClass<string, double>("sadfsd"); //Not implemented, wasn't able to prevent the construction.

  oClass1.doSomething(0.4); //Breaks at compile time

But so far I wasn't able to make .net accept Generic Extension with less arguments than parameters

I can call the interface explicitly, which is horrible verbose defeating the purpose of all this.

oClass.doSomething < MyClass<int, double>,int,double>(0.5);

I thought of working that around with a wrapper:

static class MyClassExtension{
    private static void wrappedDoSomething<P, T, U>(this P oTh, U u) 
    where P : MyClass<T, U>, ISomePolicy<T, U>
    {
        oTh._doSomething(u);
    }

    public static void doSomething<T, U>(this MyClass<T, U> oTh, U u)

    {
        oTh.wrappedDoSomething<MyClass<T, U>, T, U>(u);
    }
}

But the wrapper can't resolve both types for the wrapped function, failing with:

Error 1 The type 'MyClass' cannot be used as type parameter 'P' in the generic type or method 'MyClassExtension.wrappedDoSomething(P, U)'. There is no implicit reference conversion from 'MyClass' to 'ISomePolicy'

Any insights to fix the parameters issue or redesign all this are appreciated.


For context this would be used to wrap I/O translators. T in my case would be the target I/O format, and U the object representation of that data used by my framework.

I'm aware that this can be easily achieved with delegates or interfaces, but the objective is that the framework user easily instantiates the desired translation, and if an implementation doesn't exists, it can be trivially added to a common interface.


EDIT: Resolving a generic method from inside another generic method/class neither seems to work on mono.

解决方案

Tried your code, but even simple calls did not work out of box. Main problem is that MyClass contains unknown element type 'myEement' - that type cannot be deduced from function call parameters. However - if you make a generalization and omit object type - your sample will work in out of box manner:

using System;
using System.Collections.Generic;

interface ISomePolicy<U> 
{
    void _doSomething(U u);
}

public class MyClass<U> :
     ISomePolicy<double>,
     ISomePolicy<int>
{
    internal object myEement { get; set; }

    public MyClass(object Element)
    {
        myEement = Element;
    }

    void ISomePolicy<double>._doSomething(double u)
    {
        Console.WriteLine("this is double");
    }

    void ISomePolicy<int>._doSomething(int u)
    {
        Console.WriteLine("this is int");
    }
}

static class MyClassExtension
{
    public static void doSomething<P, U>(this P oTh, U u) where P : ISomePolicy<U>
    {
        oTh._doSomething(u);
    }
}

class Program
{
    static void Main()
    {
        MyClass<double> oClass = new MyClass<double>(3);
        oClass.doSomething(0.5); //This works
        oClass.doSomething(1);   //This works            
        //oClass.doSomething("Will not work");
    }
}

What is up to myEement (or you probably meant myElement) - you can get's it's type at run-time if necessary.

myElement.GetType(), or cast to it - e.g.
if( myElement is int ) DoSomethingWithInt( (int) myElement );

However - reflection always might slow down your execution. If you don't intend to create super heavy class hierarchy with huge amount of instances - then this should be sufficient for your needs.

这篇关于实现多参数C ++使用策略模式像C#的行为模板的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆