C# 如何在不使用子接口或显式类的情况下组合接口

C# 如何在不使用子接口或显式类的情况下组合接口,c#,interface,C#,Interface,我试图找出一种简单的方法来组合接口,而不创建新的子接口,因为接口具有多维关系 interface IAnimal {} interface ISwimmingAnimal : IAnimal {} interface IVertebrate : IAnimal {} interface IMammal : IVertebrate { IMammal Process(); } interface IInvertebrate : IAnimal {} interface IMoll

我试图找出一种简单的方法来组合接口,而不创建新的子接口,因为接口具有多维关系

interface IAnimal {}

interface ISwimmingAnimal : IAnimal {}

interface IVertebrate : IAnimal {}

interface IMammal : IVertebrate
{
    IMammal Process();
}

interface IInvertebrate : IAnimal {}

interface IMollusc : IInvertebrate
{
    IMollusc Process(object data);
}
因此,一些具体的类将是

class Vertebrate : IVertebrate {}

class SwimmingInvertebrate : ISwimmingAnimal, IInvertebrate {}

class SwimmingMammal : ISwimmingAnimal, IMammal
{
    IMammal Process();
}
不需要合成界面,例如
iswimminganimalintrovate
iswimminganimalmmal

在我需要使用包含某些组合类型实例(理论上我想要的)的类/接口之前,一切都很好:

处理过的脊椎动物
不是
未经处理的脊椎动物

我大致看到了三种解决方法:

  • 我可以分解并创建合成界面,杀死任何 简单的依赖注入
  • 我可以创建虚拟抽象基类(希望没有什么需要 深层继承链),消除任何依赖的可能性 注射
  • 或者我可以用魔杖打败C#编译器,直到它变软 并允许就地接口组合

我认为最接近您想要的是以下设置:

public interface IAnimal { }
public interface IVertebrate<out TAnimal>: IAnimal where TAnimal : IAnimal { }
public interface IInvertebrate<out TAnimal>: IAnimal where TAnimal : IAnimal { }
public interface ISwimmingAnimal : IAnimal { }
public interface ISwimmingVertebrate : IVertebrate<ISwimmingAnimal> { }
public interface ISwimmingInvertebrate : IInvertebrate<ISwimmingAnimal> { }
公共接口IAnimal{}
公共接口:IAnimal其中TAnimal:IAnimal{}
公共接口IInvertebrate:IAnimal其中TAnimal:IAnimal{}
公共接口是wimmingAnimal:IAnimal{}
公共界面是温明脊椎动物:伊夫特拉{}
公共接口是无脊椎动物:IInvertebrate{}
请注意,您仍然在创建接口之间的依赖关系。现在,您的收藏将如下所示:

public interface IAnimalsCollection<TAnimal, TVertebrate, TInvertebrate>
    where TAnimal: IAnimal
    where TVertebrate: IVertebrate<TAnimal>
    where TInvertebrate: IInvertebrate<TAnimal>
{
    IEnumerable<IAnimal> Animals { get; }
    IEnumerable<TVertebrate> Vertebrates { get; }
    IEnumerable<TInvertebrate> Invertebrates { get; }
    ....
}

public class AnimalsCollection<TAnimal, TVertebrate, TInvertebrate> : IAnimalsCollection<TAnimal, TVertebrate, TInvertebrate>
    where TAnimal : IAnimal
    where TVertebrate : IVertebrate<TAnimal>
    where TInvertebrate : IInvertebrate<TAnimal>
{
    public AnimalsCollection(IEnumerable<TVertebrate> vertebrates, IEnumerable<TInvertebrate> invertebrates)
    {
        Vertebrates = vertebrates;
        Invertebrates = invertebrates;
    }

    public IEnumerable<IAnimal> Animals => Vertebrates.Cast<IAnimal>().Concat(Invertebrates.Cast<IAnimal>());     
    public IEnumerable<TInvertebrate> Invertebrates { get; }
    public IEnumerable<TVertebrate> Vertebrates { get; }
}
公共接口IAnimalsCollection
塔尼马尔在哪里
其中TVertebrate:IVertebrate
哪里有脊椎动物:脊椎动物
{
IEnumerable动物{get;}
IEnumerable脊椎动物{get;}
IEnumerable无脊椎动物{get;}
....
}
公共类动物集合:IAnimalsCollection
塔尼马尔在哪里
其中TVertebrate:IVertebrate
哪里有脊椎动物:脊椎动物
{
公共动物采集(IEnumerable脊椎动物、IEnumerable无脊椎动物)
{
脊椎动物=脊椎动物;
无脊椎动物=无脊椎动物;
}
公共IEnumerable动物=>脊椎动物.Cast().Concat(无脊椎动物.Cast());
公共可数无脊椎动物{get;}
公共可数脊椎动物{get;}
}
一些具体类型:

public abstract class SwimmingAnimal: ISwimmingAnimal { }
public class JellyFish: IInvertebrate<SwimmingAnimal> { }
public class Fish: IVertebrate<SwimmingAnimal> { }
公共抽象类swiminganimal:ISwimmingAnimal{}
公共级水母:水母{}
公共级鱼类:伊夫特拉特{}
现在,您可以仅使用接口实例化具体集合:

var swimmingCollection = new AnimalsCollection<ISwimmingAnimal, IVertebrate<ISwimmingAnimal>, IInvertebrate<ISwimmingAnimal>>(Enumerable.Empty<Fish>(), Enumerable.Empty<JellyFish>());
var swimmingCollection=newanimalscolection(Enumerable.Empty(),Enumerable.Empty());

关键字已经在您的问题中。作文不是继承@那么我不确定我自己的解释是否正确。我不想要一个能做a、B和C的类,我想要一个能保存{IA、IB}和{IA IC}实例而不定义IAB和IAC中间接口的类。但是你的例子中所有的
IB
IC
都是
IA
,为什么需要约束这两者?@InBetween,因为我想使用IB和IC将公开的方法/属性/任何东西。实际上,它是一个类(如示例所示),包含{iaia}、{iaib}和{iaic}。也就是说,我希望其他两种类型不仅可以转换为IA(它们的基本接口),还可以转换为IA(与其自身无关的派生接口)。不幸的是,在访问具有非空集合的动物时,我遇到了一个无效的强制转换异常(无法将“Fish”类型的对象强制转换为“ISwimmingAnimal”类型)。我一直在尝试将你的建议代码和我的合并(TVertebrate:TAnimal,IVertebrate)。“不管怎样,这都是我一直试图避免的——创建中间合成接口。”托利·伍普斯犯了一个错误
Animals
必须返回一个
IEnumerable
,返回一个
IEnumerable
是没有意义的,因为你不能让一个接口扩展一个泛型类型
IVertebrate
IInvertebrate
必须实现
IAnimal
。修正代码。是的,修正了它(我的要求仍然允许)。它使代码更接近于我的“合并”版本——但是哦,简单多了。我已经检查并扩展了它,比如说,
IMammal:IVertebrate,其中TAnimal:IAnimal
仍然使用
var-animals=new-animalcollection(…)
。我会等一天接受答案,以防有人抓住了我们错过的东西或抓住了机会。非常感谢。这不是我想要的(否则我就不会问这个问题),但也没有我担心的那么糟糕。
public interface IAnimalsCollection<TAnimal, TVertebrate, TInvertebrate>
    where TAnimal: IAnimal
    where TVertebrate: IVertebrate<TAnimal>
    where TInvertebrate: IInvertebrate<TAnimal>
{
    IEnumerable<IAnimal> Animals { get; }
    IEnumerable<TVertebrate> Vertebrates { get; }
    IEnumerable<TInvertebrate> Invertebrates { get; }
    ....
}

public class AnimalsCollection<TAnimal, TVertebrate, TInvertebrate> : IAnimalsCollection<TAnimal, TVertebrate, TInvertebrate>
    where TAnimal : IAnimal
    where TVertebrate : IVertebrate<TAnimal>
    where TInvertebrate : IInvertebrate<TAnimal>
{
    public AnimalsCollection(IEnumerable<TVertebrate> vertebrates, IEnumerable<TInvertebrate> invertebrates)
    {
        Vertebrates = vertebrates;
        Invertebrates = invertebrates;
    }

    public IEnumerable<IAnimal> Animals => Vertebrates.Cast<IAnimal>().Concat(Invertebrates.Cast<IAnimal>());     
    public IEnumerable<TInvertebrate> Invertebrates { get; }
    public IEnumerable<TVertebrate> Vertebrates { get; }
}
public abstract class SwimmingAnimal: ISwimmingAnimal { }
public class JellyFish: IInvertebrate<SwimmingAnimal> { }
public class Fish: IVertebrate<SwimmingAnimal> { }
var swimmingCollection = new AnimalsCollection<ISwimmingAnimal, IVertebrate<ISwimmingAnimal>, IInvertebrate<ISwimmingAnimal>>(Enumerable.Empty<Fish>(), Enumerable.Empty<JellyFish>());