Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/extjs/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 转换到多个接口_C#_Generics_Casting - Fatal编程技术网

C# 转换到多个接口

C# 转换到多个接口,c#,generics,casting,C#,Generics,Casting,可能重复: 我相当确定您不能这样做,所以我想知道是否有解决方法,但我需要/想要强制转换一个对象来表示多个接口,以便与通用约束一起使用。例如: public void Foo<T>(T t) where T : IInterfaceA, IInterfaceB { } public void Foo(T)其中T:IInterfaceA,IInterfaceB { } 如果我有一个对象,我想说像vart=(IInterfaceA | IInterfaceB)someObj这样我就可

可能重复:

我相当确定您不能这样做,所以我想知道是否有解决方法,但我需要/想要强制转换一个对象来表示多个接口,以便与通用约束一起使用。例如:

public void Foo<T>(T t) where T : IInterfaceA, IInterfaceB
{
}
public void Foo(T)其中T:IInterfaceA,IInterfaceB
{
}
如果我有一个对象,我想说像
vart=(IInterfaceA | IInterfaceB)someObj
这样我就可以将
t
传递到这个方法中

有什么好办法吗?我使用的是C#3.5,因此没有可用的动态,但如果可以使用动态,请将其发布。

不,没有办法。
唯一接近的是创建另一个接口,该接口继承了这两个接口。但所有类都需要实现第三个接口,而不是另外两个接口,所以在大多数情况下,这是不实际的

只需将其转换到您当时需要的界面即可

更新:
我能看到的唯一方法是创建一个实现这些接口的容器类:

class Container : IInterfaceA, IInterfaceB
{
    private object _obj;

    public Container(object obj)
    {
        // Check that the object really implements those two interfaces.

        _obj = obj;
    }

    void IInterfaceA.Method1()
    {
        ((IInterfaceA)_obj).Method1();
    }

    // And so on for all methods of the interfaces.
} 
这会将对象强制转换为T,而不是两个接口。。。因此,这取决于你是否能确保这一点



两次引用一个实例。

一种可能的方法是继承接口。将通用功能移动到父界面,该界面应在上述场景中使用。

您可以重新构造继承以实现您的目标

public class ArrayList : IList, ICollection, IEnumerable, ICloneable
public interface IList : ICollection, IEnumerable
请注意,ArrayList源自IList,它继承了ArrayList中已经包含的两个接口。

EDIT

尽管有下面的答案,我想说更好的解决方案是大多数其他答案所指向的。(这假设您可以重新定义实现这两个接口的多个类。)

创建一个从InterfaceA和InterfaceB继承的接口,然后,对于实现接口A和B的所有类,用新接口替换这些接口。之前:

class SomeClass : IInterfaceA, IInterfaceB { }
class AnotherClass : IInterfaceA, IInterfaceB { }
class AdditionalClass : IInterfaceA, IInterfaceB { }
之后:

interface IInterfaceC : IInterfaceA, IInterfaceB { }
class SomeClass : IInterfaceC { }
class AnotherClass : IInterfaceC { }
class AdditionalClass : IInterfaceC { }
因此,Foo的实现相当简单。同样,由于您在编译时不知道手头上有什么类型,所以可以将其声明为

public void Foo(IInterfaceC someObj) { }
结束编辑


您可以使用反射来实现,尽管有些人会说这并不特别“漂亮”:


您不希望在转换后成为什么类型?检查.net framework 4的协方差概念,这可能会有所帮助,但为此您需要更改实现。我们不能继承接口吗?@CJBrew我猜它将是一种不存在的类型,但同时实现两个接口。类似于匿名类型。@Ramesh是的,这是我考虑的另一个解决方案,但出于各种原因,我不想走这条路(尽管我可能不得不走!)对不起,我认为我的问题措辞不好,我不想在方法中进行转换,我想做外部的,这样我就可以把它传递到方法中,而不必强制调用。只要使用实现这两者的任何类型。是的,当我调用Foo时,我不知道编译时的类型是什么,我无法将其转换为已定义的类型,因为有多个类实现了两个接口。如果有一个类的实例实现了两个接口,但没有从容器类继承,那么容器类将无法工作。换句话说,例如,System.String实现了IComparable和IEnumerable。如果创建
类X:IComparable,IEnumerable
,则无法将字符串分配给此类型的变量,反之亦然。@phoog:我不懂。您不想将
字符串
分配给
X
,而是将其传递给构造函数…啊哈,我明白了。对不起,我读得太快了,我不明白你建议的方法。
class SomeClass : IInterfaceA, IInterfaceB { }
class AnotherClass : IInterfaceA, IInterfaceB { }
class AdditionalClass : IInterfaceA, IInterfaceB { }
interface IInterfaceC : IInterfaceA, IInterfaceB { }
class SomeClass : IInterfaceC { }
class AnotherClass : IInterfaceC { }
class AdditionalClass : IInterfaceC { }
public void Foo(IInterfaceC someObj) { }
public class FooClass
{
    public void Foo<T> (T t) where T : IInterfaceA, IInterfaceB
    {
        //... do your thing here
    }
    private static void Example(object someObj)
    {
        var type = someObj.GetType();
        if(typeof(IInterfaceA).IsAssignableFrom(type) && typeof(IInterfaceB).IsAssignableFrom(type))
        {
            var genericMethod = typeof(FooClass).GetMethod("Foo");
            var constructedMethod = genericMethod.MakeGenericMethod(type);
            var instance = new FooClass();
            var result = constructedMethod.Invoke(instance, new [] { someObj });
            Assert.IsNull(result);
        }
    }
}
private void PrivateFoo(IInterfaceA objA, IInterfaceB objB)
{
    if (!ReferenceEquals(objA, objB))
        throw new ArgumentException("objA and objB must refer to the same object");

    //... do your thing here
}
public void Foo(object someObj)
{
    PrivateFoo((IInterfaceA)someObj, (IInterfaceB)someObj);
}