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>());