是否可以指定一个类型参数的通用约束从另一个类型转换? [英] Is it possible to specify a generic constraint for a type parameter to be convertible FROM another type?

查看:121
本文介绍了是否可以指定一个类型参数的通用约束从另一个类型转换?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我使用以下方法编写一个库:

  public class Bar {/ * ... * /} 

公共类SomeWeirdClass< T>
其中T:???
{
public T BarMaker(Bar b)
{
// ...玩b
T t =(T)b
return( T)b;


$ / code>

稍后,我希望用户通过定义他们自己的类型可以转换成Bar并使用SomeWeirdClass的'工厂'。

  public class Foo 
{
public static explicit operator Foo(Bar f)
{
return new Bar();



public class Demo
{
public static void demo()
{
Bar b = new Bar ();
SomeWeirdClass< Foo> weird = new SomeWeirdClass< Foo>();
Foo f = weird.BarMaker(b);


code $


如果我将其中T:Foo 但问题是我不知道Foo在库的编译时,我真的想要更类似于的地方,其中T:某些类可以被实例化,给定一个Bar



这可能吗?从我的有限知识来看,它似乎并不是,但.NET框架和它的用户的独创性总让我感到惊讶......

这可能与至少,静态接口方法的想法,我可以看到能够指定工厂方法来创建对象的价值(类似于您已经可以执行的相同方式,其中T:new()



编辑:解决方案 - 感谢Nick和bzIm - 对于其他读者,我将提供完整的解决方案,据我了解:
编辑2:此解决方案需要Foo公开默认构造函数。

 对于一个甚至是 stupider 更好的解决方案,并不需要这个。 public class Bar {} 

public class SomeWeirdClass< T>
其中T:IConvertibleFromBar< T> ;, new()
{
public T BarMaker(Bar b)
{
T t = new T();
t.Convert(b);
return t;
}
}

公共接口IConvertibleFromBar< T>
{
T Convert(Bar b);
}

公共类Foo:IConvertibleFromBar< Foo>
{
public static显式运算符Foo(Bar f)
{
return null;
}

public Foo Convert(Bar b)
{
return(Foo)b;



public class Demo
{
public static void demo()
{
Bar b = new Bar ();
SomeWeirdClass< Foo> weird = new SomeWeirdClass< Foo>();
Foo f = weird.BarMaker(b);
}
}

edit2:解决方案2 :创建一个类型转换器工厂使用:

  #region库定义的代码

public class Bar { }

公共类SomeWeirdClass< T,TFactory>
其中TFactory:IConvertorFactory< Bar,T> ;, new()
{
private static TFactory convertor = new TFactory();

public T BarMaker(Bar b)
{
return convertor.Convert(b);
}
}

公共接口IConvertorFactory< TFrom,TTo>
{
TTo Convert(TFrom from);
}

#endregion

#区域用户定义的代码

公共类BarToFooConvertor:IConvertorFactory< Bar,Foo>
{
public Foo Convert(Bar from)
{
return(Foo)from;



public class Foo
{
public Foo(int a){}

public static explicit operator Foo(Bar f)
{
return null;
}

public Foo Convert(Bar b)
{
return(Foo)b;



#endregion

public class Demo
{
public static void demo()
{
Bar b = new Bar();
SomeWeirdClass< Foo,BarToFooConvertor> weird = new SomeWeirdClass< Foo,BarToFooConvertor>();
Foo f = weird.BarMaker(b);
}
}


解决方案

I不要认为语言中必须使用语法上的酷语法。您的问题的一个可能的解决方案可能是定义一个可转换接口:

  public interface IConvertible< T> 
其中T:new()//可能需要这个
{
T Convert();
}

然后你的课程可以是:

  public class Foo:IConvertible< Bar> 
{
}

我认为这会让您接近您想要的位置是......在你的问题中,所有的Foo和Bar都会让你很难确定你的意图是什么。希望这会有所帮助。



编辑:在约束处添加...您可能必须能够在可转换类中创建新实例。
$ b

编辑2:使得Foo继承自 ICovertible< Bar>


Suppose I write a library with the following:

public class Bar { /* ... */ }

public class SomeWeirdClass<T>
    where T : ???
{
    public T BarMaker(Bar b)
    {
        // ... play with b
        T t = (T)b
        return (T) b;
    }
}

Later, I expect users to use my library by defining their own types which are convertible to Bar and using the SomeWeirdClass 'factory'.

public class Foo
{
    public static explicit operator Foo(Bar f)
    {
        return new Bar();
    }
}

public class Demo
{
    public static void demo()
    {
        Bar b = new Bar();
        SomeWeirdClass<Foo> weird = new SomeWeirdClass<Foo>();
        Foo f = weird.BarMaker(b);
    }
}

this will compile if i set where T : Foo but the problem is that I don't know about Foo at the library's compile time, and I actually want something more like where T : some class that can be instantiated, given a Bar

Is this possible? From my limited knowledge it does not seem to be, but the ingenuity of the .NET framework and its users always surprises me...

This may or not be related to the idea of static interface methods - at least, I can see the value in being able to specify the presence of factory methods to create objects (similar to the same way that you can already perform where T : new())

edit: Solution - thanks to Nick and bzIm - For other readers I'll provide a completed solution as I understand it: edit2: This solution requires Foo to expose a public default constructor. For an even stupider better solution that does not require this see the very bottom of this post.

public class Bar {}

public class SomeWeirdClass<T>
    where T : IConvertibleFromBar<T>, new()
{
    public T BarMaker(Bar b)
    {
        T t = new T();
        t.Convert(b);
        return t;
    }
}

public interface IConvertibleFromBar<T>
{
    T Convert(Bar b);
}

public class Foo : IConvertibleFromBar<Foo>
{
    public static explicit operator Foo(Bar f)
    {
        return null;
    }

    public Foo Convert(Bar b)
    {
        return (Foo) b;
    }
}

public class Demo
{
    public static void demo()
    {
        Bar b = new Bar();
        SomeWeirdClass<Foo> weird = new SomeWeirdClass<Foo>();
        Foo f = weird.BarMaker(b);
    }
}

edit2: Solution 2: Create a type convertor factory to use:

#region library defined code

public class Bar {}

public class SomeWeirdClass<T, TFactory>
    where TFactory : IConvertorFactory<Bar, T>, new()
{
    private static TFactory convertor = new TFactory();

    public T BarMaker(Bar b)
    {
        return convertor.Convert(b);
    }
}

public interface IConvertorFactory<TFrom, TTo>
{
    TTo Convert(TFrom from);
}

#endregion

#region user defined code

public class BarToFooConvertor : IConvertorFactory<Bar, Foo>
{
    public Foo Convert(Bar from)
    {
        return (Foo) from;
    }
}

public class Foo
{
    public Foo(int a) {}

    public static explicit operator Foo(Bar f)
    {
        return null;
    }

    public Foo Convert(Bar b)
    {
        return (Foo) b;
    }
}

#endregion

public class Demo
{
    public static void demo()
    {
        Bar b = new Bar();
        SomeWeirdClass<Foo, BarToFooConvertor> weird = new SomeWeirdClass<Foo, BarToFooConvertor>();
        Foo f = weird.BarMaker(b);
    }
}

解决方案

I don't think there is necessarily a syntactically cool way to do this built into the language. One possible solution to your problem could be to define a convertible interface:

public interface IConvertible<T>
    where T :  new()   // Probably will need this
{
    T Convert();
}

Then your class could be:

public class Foo : IConvertible<Bar>
{
}

I think this gets you close to where you want to be... All the Foo's and Bar's in your question sometimes make it hard to determine exactly what your intent is. Hope this helps.

Edit: Added where constraint... you will probably have to be able to create a new instance in your convertible class.

Edit 2: Made Foo inherit from ICovertible<Bar>

这篇关于是否可以指定一个类型参数的通用约束从另一个类型转换?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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