0

是否可以在函数体内使用通用机制?

例如

if (!(someClass is IClass<T, G> where T : someInterface, G : anotherInterface))
{
    return;
 }

或像这样进行铸造:

var v = (IClass <T, G> where T : someInterface, G: anotherInterface)something;
4

4 回答 4

1

对于第一个示例,是的 - 您只需要指定类型:

if (!(someClass is IClass<ISomeInterface, IAnotherInterface>))
{
    return;
 }

另一个大同小异:

var v = (IClass <ISomeInterface, IAnotherInterface>)something;

虽然它可能更好用as

var v = something as IClass <ISomeInterface, IAnotherInterface>;
if(v != null)
{
    // Do something.
}

上面的第二行很重要 - 通过使用as代替直接强制转换,InvalidCastException如果失败,您将不会得到,但v如果使用强制转换失败,则会为空as。如果您的施法尝试无效,此技术可让您更好地控制失败。(考虑一下为什么转换会无效:如果这代表一种情况,您知道更久知道世界是什么样子,那么InvalidCastException这可能是正确的方法。如果对象不是接口的实例是合理的,那么as您的朋友。)

于 2012-12-12T08:09:50.370 回答
1

你可以这样做,但你必须确保你的界面是协变的:

interface IClass<out T, out S>
{
    // Methods that can return a T or S but not accept one as input
}

通过将类型参数标记为out,您基本上是在说“我只会这个接口中得到 aT或 a ”。例如,因为您只能从中取出 a,但仅仅是因为您可以将 a放入列表中并取出一个。S IEnumerable<out T>TList<T>T

已经这样定义了你的接口, anIClass<string, string> an IClass<object, object>:你知道你IClass<string, string>只会给你 a string,但是既然 astring是 anobject那么那很好,如果你将它分配给 anIClass<object, object>你知道它只会给你一个object.

(如果您的接口允许您将 a或 an放入某物,则您不能这样做。如果是这种情况,并且您将您分配给 an ,您可以尝试将 an放入其中,但它会失败,因为基础类只真正接受 a 。)TS IClass<string, string>IClass<object, object>intstring

这让你做的是

if (!(something is IClass<object, object>))
{
    return;
}

或者

var v = (IClass<object, object>)something;

something如果实际上一个实现的对象,例如,两者都将起作用IClass<string, string>

于 2012-12-12T08:36:18.377 回答
0

你可以试试这个:

if (!(someClass is IClass<someInterface, anotherInterface>)
{
    return;
}

或通过反射:

var t = someClass.GetType()
Type[] typeParameters = t.GetGenericArguments();
if (!typeParameters[0].IsSubclassOf(typeof(someInterface)) || 
    !typeParameters[1].IsSubclassOf(typeof(anotherInterface)))
{
    return;
}
于 2012-12-12T08:12:08.490 回答
0

where约束将应用于泛型方法本身。您可以毫无问题地使用所需的类型。

附带说明:不要检查false,从长远来看会更加混乱。

if (someClass is IClass<someInterface, anotherInterface>)
{
    // your code
}
// else { return; } // no longer needed!

在一个通用方法中扩展和封装代码,它看起来像这样:

void myMethod<T, U>()
    where T : someInterface
    where U : anotherInterface
{
    if (someClass is IClass<T, U>)
    {
        // your code
    }
    // else { return; } // no longer needed!
}
于 2012-12-12T08:14:55.720 回答