C# 运算符 as 和泛型类
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/693463/
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
Operator as and generic classes
提问by abatishchev
I'm writing .NET On-the-Flycompiler for CLR scripting and want execution method make generic acceptable:
我正在为 CLR 脚本编写.NET On-the-Fly编译器,并希望执行方法使通用可接受:
object Execute()
{
return type.InvokeMember(..);
}
T Execute<T>()
{
return Execute() as T; /* doesn't work:
The type parameter 'T' cannot be used with the 'as' operator because
it does not have a class type constraint nor a 'class' constraint */
// also neither typeof(T) not T.GetType(), so on are possible
return (T) Execute(); // ok
}
But I think operator as
will be very useful: if result type isn't T
method will return null
, instead of an exception! Is it possible to do?
但我认为运算符as
会非常有用:如果结果类型不是T
方法将返回null
,而不是异常!有可能吗?
采纳答案by Daniel Earwicker
You need to add
你需要添加
where T : class
to your method declaration, e.g.
到您的方法声明,例如
T Execute<T>() where T : class
{
By the way, as a suggestion, that generic wrapper doesn't really add much value. The caller can write:
顺便说一句,作为一个建议,通用包装器并没有真正增加太多价值。调用者可以写:
MyClass c = whatever.Execute() as MyClass;
Or if they want to throw on fail:
或者,如果他们想抛出失败:
MyClass c = (MyClass)whatever.Execute();
The generic wrapper method looks like this:
通用包装器方法如下所示:
MyClass c = whatever.Execute<MyClass>();
All three versions have to specify exactly the same three entities, just in different orders, so none are any simpler or any more convenient, and yet the generic version hides what is happening, whereas the "raw" versions each make it clear whether there will be a throw or a null
.
所有三个版本都必须指定完全相同的三个实体,只是顺序不同,所以没有一个更简单或更方便,然而通用版本隐藏了正在发生的事情,而“原始”版本每个都清楚地表明是否会有是一个投掷或一个null
。
(This may be irrelevant to you if your example is simplified from your actual code).
(如果您的示例是从您的实际代码简化的,这可能与您无关)。
回答by Samuel
You cannot use the as
operator with a generic type with no restriction. Since the as
operator uses null to represent that it was not of the type, you cannot use it on value types. If you want to use obj as T
, T
will haveto be a reference type.
您不能在as
没有限制的泛型类型中使用运算符。由于as
运算符使用 null 来表示它不是该类型,因此您不能在值类型上使用它。如果要使用obj as T
,T
则必须是引用类型。
T Execute<T>() where T : class
{
return Execute() as T;
}
回答by Cecil Has a Name
It seems like you are just adding a wrapper method for casting to the type the user wants, thus only adding overhead to the execution. For the user, writing
似乎您只是添加了一个包装方法来转换为用户想要的类型,因此只会增加执行的开销。对于用户,写
int result = Execute<int>();
isn't much different from
与
int result = (int)Execute();
You can use the outmodifier to write the result into a variable in the caller's scope, and return a boolean flag to tell whether it succeeded:
您可以使用out修饰符将结果写入调用者范围内的变量,并返回一个布尔标志来判断它是否成功:
bool Execute<T>(out T result) where T : class
{
result = Execute() as T;
return result != null;
}
回答by Charlie Flowers
Is there a chance that Execute() might return a value type? If so, then you need Earwicker's method for class types, and another generic method for value types. Might look like this:
Execute() 是否有可能返回值类型?如果是这样,那么您需要针对类类型使用 Earwicker 的方法,以及针对值类型使用另一种泛型方法。可能看起来像这样:
Nullable<T> ExecuteForValueType<T> where T : struct
The logic inside that method would say
该方法内部的逻辑会说
object rawResult = Execute();
Then, you'd have to get the type of rawResult and see if it can be assigned to T:
然后,您必须获取 rawResult 的类型并查看它是否可以分配给 T:
Nullable<T> finalReturnValue = null;
Type theType = rawResult.GetType();
Type tType = typeof(T);
if(tType.IsAssignableFrom(theType))
{
finalReturnValue = tType;
}
return finalReturnValue;
Finally, make your original Execute message figure out which T is has (class or struct type), and call the appropriate implementation.
最后,让您的原始 Execute 消息找出 T 具有哪个(类或结构类型),并调用适当的实现。
Note: This is from rough memory. I did this about a year ago and probably don't remember every detail. Still, I hope pointing you in the general direction helps.
注意:这是粗略的记忆。我大约一年前做过这件事,可能不记得每一个细节。不过,我希望为您指明大方向会有所帮助。
回答by Felix Keil
This small piece of code is an exception safe substitution for the as-keyword:
这段代码是as关键字的异常安全替代:
return Execute() is T value ? value : default(T)
It uses the pattern matching feature introduced with C# 7. Use it, if you don't want to restrict the generic parameter to a reference type
它使用 C# 7 引入的模式匹配功能。如果您不想将泛型参数限制为引用类型,请使用它