C# 将对象转换为通用接口

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/222403/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 18:45:01  来源:igfitidea点击:

Casting an object to a generic interface

c#genericsinterfacecasting

提问by robertkroll

I have the following interface:

我有以下界面:

internal interface IRelativeTo<T> where T : IObject
{
    T getRelativeTo();
    void setRelativeTo(T relativeTo);
}

and a bunch of classes that (should) implement it, such as:

和一堆(应该)实现它的类,例如:

public class AdminRateShift : IObject, IRelativeTo<AdminRateShift>
{
    AdminRateShift getRelativeTo();
    void setRelativeTo(AdminRateShift shift);
}

I realise that these three are not the same:

我意识到这三个不一样:

IRelativeTo<>
IRelativeTo<AdminRateShift>
IRelativeTo<IObject>

but nonetheless, I need a way to work with all the different classes like AdminRateShift (and FXRateShift, DetRateShift) that should all implement IRelativeTo. Let's say I have an function which returns AdminRateShift as an Object:

但是尽管如此,我需要一种方法来处理所有不同的类,比如 AdminRateShift(和 FXRateShift、DetRateShift),这些类都应该实现 IRelativeTo。假设我有一个将 AdminRateShift 作为对象返回的函数:

IRelativeTo<IObject> = getObjectThatImplementsRelativeTo(); // returns Object

By programming against the interface, I can do what I need to, but I can't actually cast the Object to IRelativeTo so I can use it.

通过针对接口编程,我可以做我需要做的事情,但我实际上无法将 Object 转换为 IRelativeTo 以便我可以使用它。

It's a trivial example, but I hope it will clarify what I am trying to do.

这是一个微不足道的例子,但我希望它能澄清我想要做什么。

采纳答案by Marc Gravell

If I understand the question, then the most common approach would be to declare a non-generic base-interface, i.e.

如果我理解这个问题,那么最常见的方法是声明一个非通用的基本接口,即

internal interface IRelativeTo
{
    object getRelativeTo(); // or maybe something else non-generic
    void setRelativeTo(object relativeTo);
}
internal interface IRelativeTo<T> : IRelativeTo
    where T : IObject
{
    new T getRelativeTo();
    new void setRelativeTo(T relativeTo);
}

Another option is for you to code largely in generics... i.e. you have methods like

另一种选择是让您主要使用泛型进行编码……即您有类似的方法

void DoSomething<T>() where T : IObject
{
    IRelativeTo<IObject> foo = // etc
}

If the IRelativeTo<T>is an argument to DoSomething(), then usuallyyou don't need to specify the generic type argument yourself - the compiler will infer it - i.e.

如果IRelativeTo<T>是 的参数DoSomething(),那么通常您不需要自己指定泛型类型参数 - 编译器会推断它 - 即

DoSomething(foo);

rather than

而不是

DoSomething<SomeType>(foo);

There are benefits to both approaches.

这两种方法都有好处。

回答by Grzenio

unfortunately inheritance doesn't work with generics. If your function expects IRelativeTo, you can make the function generic as well:

不幸的是,继承不适用于泛型。如果您的函数需要 IRelativeTo,您也可以使该函数通用:

void MyFunction<T>(IRelativeTo<T> sth) where T : IObject
{}

If I remember correctly, when you use the function above you don't even need to specify the type, the compiler should figure it out based on the argument you supply.

如果我没记错的话,当你使用上面的函数时,你甚至不需要指定类型,编译器应该根据你提供的参数来计算。

If you want to keep a reference to one of these IRelativeTo objects inside a class or method (and you don't care what T is that), you need to make this class/method generic again.

如果您想在类或方法中保留对这些 IRelativeTo 对象之一的引用(并且您不关心 T 是什么),则需要再次使此类/方法通用。

I agree, it is a bit of pain.

我同意,这有点痛苦。

回答by Mark Cidade

If all you care about is that IRelativeTo deals with IObjects then you don't need to make it generic:

如果您只关心 IRelativeTo 处理 IObjects,那么您不需要使其通用:

interface IRelativeTo
 {
   IObject getRelativeTo();
   void setRelativeTo(IObject relativeTo)
 }

The implementing classes may still be generic, however:

实现类可能仍然是通用的,但是:

abstract class RelativeTo<T>  : IRelativeTo where T : IObject
 {  
   public virtual T getRelativeTo() {return default(T);}

   public virtual void setRelativeTo(T relativeTo) {}

   IObject IRelativeTo.getRelativeTo() {return this.getRelativeTo(); }

   void IRelativeTo.setRelativeTo(IObject relativeTo) 
    { this.setRelativeTo((T) relativeTo);
    }
 }

class AdminRateShift :  RelativeTo<AdminRateShift>, IObject {}

Then you can do this:

然后你可以这样做:

  IRelativeTo irt = new AdminRateShift();
  IObject o = irt.getRelativeTo();
  irt.setRelativeTo(o);