简体   繁体   中英

c# cannot cast object to interface in a method with multiple generic parameters

I'm playing with Generics and in a method with two generic parameters try to cast an object to interface, which doesn't work. The below code demonstrates problem:

    private void GenericMethod<T, U>() 
        where T : Block
        where U : IBlock
    {
        var list = new List<T>();

        // this casting works
        var item = new Block();
        var iItem = (IBlock)item;

        foreach (var l in list)
        { 
            // this doesn't compile
            var variable = (U)l;
        }
    }

Here Block is a class and IBlock is interface implemented by this class.

Why does casting (U)l fail? How can I do it?

If T inherits from Block, and U from IBlock it does not mean T will inherit from U even if Block inherits from IBlock. For example:

public class TBlock : Block
{
   public void NewMethod() {}
}

public interface UIBlock : IBlock
{
   void AnotherNewMethod();
}

To make this example work, you'd have to change

where T : Block
where U : IBlock

to

where U : IBlock
where T : Block, U

to make sure T inherits from U.

虽然可以将T转换为IBlock,但是就规则而言,您不知道它是否可以转换为U-U实现IBLock,但可以是任何类型。

You can cast your iterator. https://dotnetfiddle.net/FgKdL8

using System;
using System.Collections.Generic;

public class Program
{
    public static void Main()
    {
        Console.WriteLine("Hello World");
    }

    private void GenericMethod<T, U>() 
        where T : Block
        where U : IBlock
    {
        var list = new List<U>();

        // this casting works
        var item = new Block();
        var iItem = (IBlock)item;

        // cast your iterator
        foreach (U l in list)
        { 

        }
    }

    public interface IBlock
    {}
    public class Block : IBlock
    {}
}

If you can guarantee that T will inherit U, you can add that constraint to the declaration:

where U : IBlock where T : Block, U

If you want the function to still work either way, but cast to U if possible (I can't really imagine why you'd want this, but...), you can do this:

public GenericMethod<T, U>()
    where T : Block
    where U : class, IBlock // must be a class to use the `as` operator 
{
    // ... 
    var variable = item as U;
} 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM