2 // delegate.cs: Delegate Handler
5 // Ravi Pratap (ravi@ximian.com)
6 // Miguel de Icaza (miguel@ximian.com)
7 // Marek Safar (marek.safar@gmail.com)
9 // Dual licensed under the terms of the MIT X11 or GNU GPL
11 // Copyright 2001 Ximian, Inc (http://www.ximian.com)
12 // Copyright 2003-2009 Novell, Inc (http://www.novell.com)
16 using System
.Reflection
;
17 using System
.Reflection
.Emit
;
18 using System
.Collections
.Generic
;
20 namespace Mono
.CSharp
{
23 // Delegate container implementation
25 public class Delegate
: TypeContainer
27 FullNamedExpression ReturnType
;
28 public readonly ParametersCompiled Parameters
;
30 Constructor Constructor
;
32 Method BeginInvokeBuilder
;
33 Method EndInvokeBuilder
;
35 static readonly string[] attribute_targets
= new string [] { "type", "return" }
;
37 public static readonly string InvokeMethodName
= "Invoke";
39 Expression instance_expr
;
40 ReturnParameter return_attributes
;
42 const Modifiers MethodModifiers
= Modifiers
.PUBLIC
| Modifiers
.VIRTUAL
;
44 const Modifiers AllowedModifiers
=
52 public Delegate (NamespaceEntry ns
, DeclSpace parent
, FullNamedExpression type
,
53 Modifiers mod_flags
, MemberName name
, ParametersCompiled param_list
,
55 : base (ns
, parent
, name
, attrs
, MemberKind
.Delegate
)
58 this.ReturnType
= type
;
59 ModFlags
= ModifiersExtensions
.Check (AllowedModifiers
, mod_flags
,
60 IsTopLevel
? Modifiers
.INTERNAL
:
61 Modifiers
.PRIVATE
, name
.Location
, Report
);
62 Parameters
= param_list
;
63 spec
= new TypeSpec (Kind
, null, this, null, ModFlags
| Modifiers
.SEALED
);
66 public override void ApplyAttributeBuilder (Attribute a
, MethodSpec ctor
, byte[] cdata
, PredefinedAttributes pa
)
68 if (a
.Target
== AttributeTargets
.ReturnValue
) {
69 if (return_attributes
== null)
70 return_attributes
= new ReturnParameter (this, InvokeBuilder
.MethodBuilder
, Location
);
72 return_attributes
.ApplyAttributeBuilder (a
, ctor
, cdata
, pa
);
76 base.ApplyAttributeBuilder (a
, ctor
, cdata
, pa
);
79 public override AttributeTargets AttributeTargets
{
81 return AttributeTargets
.Delegate
;
85 protected override bool DoDefineMembers ()
87 var ctor_parameters
= ParametersCompiled
.CreateFullyResolved (
89 new Parameter (new TypeExpression (TypeManager
.object_type
, Location
), "object", Parameter
.Modifier
.NONE
, null, Location
),
90 new Parameter (new TypeExpression (TypeManager
.intptr_type
, Location
), "method", Parameter
.Modifier
.NONE
, null, Location
)
93 TypeManager
.object_type
,
94 TypeManager
.intptr_type
98 Constructor
= new Constructor (this, System
.Reflection
.ConstructorInfo
.ConstructorName
,
99 Modifiers
.PUBLIC
, null, ctor_parameters
, null, Location
);
100 Constructor
.Define ();
103 // Here the various methods like Invoke, BeginInvoke etc are defined
105 // First, call the `out of band' special method for
106 // defining recursively any types we need:
110 if (!p
.Resolve (this))
117 // Check accessibility
118 foreach (var partype
in p
.Types
) {
119 if (!IsAccessibleAs (partype
)) {
120 Report
.SymbolRelatedToPreviousError (partype
);
121 Report
.Error (59, Location
,
122 "Inconsistent accessibility: parameter type `{0}' is less accessible than delegate `{1}'",
123 TypeManager
.CSharpName (partype
), GetSignatureForError ());
127 ReturnType
= ReturnType
.ResolveAsTypeTerminal (this, false);
128 if (ReturnType
== null)
131 var ret_type
= ReturnType
.Type
;
134 // We don't have to check any others because they are all
135 // guaranteed to be accessible - they are standard types.
137 if (!IsAccessibleAs (ret_type
)) {
138 Report
.SymbolRelatedToPreviousError (ret_type
);
139 Report
.Error (58, Location
,
140 "Inconsistent accessibility: return type `" +
141 TypeManager
.CSharpName (ret_type
) + "' is less " +
142 "accessible than delegate `" + GetSignatureForError () + "'");
146 CheckProtectedModifier ();
148 if (RootContext
.StdLib
&& TypeManager
.IsSpecialType (ret_type
)) {
149 Method
.Error1599 (Location
, ret_type
, Report
);
153 TypeManager
.CheckTypeVariance (ret_type
, Variance
.Covariant
, this);
155 InvokeBuilder
= new Method (this, null, ReturnType
, MethodModifiers
, new MemberName (InvokeMethodName
), p
, null);
156 InvokeBuilder
.Define ();
159 // Don't emit async method for compiler generated delegates (e.g. dynamic site containers)
161 if (TypeManager
.iasyncresult_type
!= null && TypeManager
.asynccallback_type
!= null && !IsCompilerGenerated
) {
162 DefineAsyncMethods (Parameters
.CallingConvention
);
168 void DefineAsyncMethods (CallingConventions cc
)
173 Parameter
[] compiled
= new Parameter
[Parameters
.Count
];
174 for (int i
= 0; i
< compiled
.Length
; ++i
)
175 compiled
[i
] = new Parameter (new TypeExpression (Parameters
.Types
[i
], Location
),
176 Parameters
.FixedParameters
[i
].Name
,
177 Parameters
.FixedParameters
[i
].ModFlags
& (Parameter
.Modifier
.REF
| Parameter
.Modifier
.OUT
),
180 ParametersCompiled async_parameters
= new ParametersCompiled (Compiler
, compiled
);
182 async_parameters
= ParametersCompiled
.MergeGenerated (Compiler
, async_parameters
, false,
184 new Parameter (new TypeExpression (TypeManager
.asynccallback_type
, Location
), "callback", Parameter
.Modifier
.NONE
, null, Location
),
185 new Parameter (new TypeExpression (TypeManager
.object_type
, Location
), "object", Parameter
.Modifier
.NONE
, null, Location
)
188 TypeManager
.asynccallback_type
,
189 TypeManager
.object_type
193 BeginInvokeBuilder
= new Method (this, null,
194 new TypeExpression (TypeManager
.iasyncresult_type
, Location
), MethodModifiers
,
195 new MemberName ("BeginInvoke"), async_parameters
, null);
196 BeginInvokeBuilder
.Define ();
199 // EndInvoke is a bit more interesting, all the parameters labeled as
200 // out or ref have to be duplicated here.
204 // Define parameters, and count out/ref parameters
206 ParametersCompiled end_parameters
;
209 foreach (Parameter p
in Parameters
.FixedParameters
) {
210 if ((p
.ModFlags
& Parameter
.Modifier
.ISBYREF
) != 0)
214 if (out_params
> 0) {
215 var end_param_types
= new TypeSpec
[out_params
];
216 Parameter
[] end_params
= new Parameter
[out_params
];
219 for (int i
= 0; i
< Parameters
.FixedParameters
.Length
; ++i
) {
220 Parameter p
= Parameters
[i
];
221 if ((p
.ModFlags
& Parameter
.Modifier
.ISBYREF
) == 0)
224 end_param_types
[param
] = Parameters
.Types
[i
];
225 end_params
[param
] = p
;
228 end_parameters
= ParametersCompiled
.CreateFullyResolved (end_params
, end_param_types
);
230 end_parameters
= ParametersCompiled
.EmptyReadOnlyParameters
;
233 end_parameters
= ParametersCompiled
.MergeGenerated (Compiler
, end_parameters
, false,
235 new TypeExpression (TypeManager
.iasyncresult_type
, Location
),
236 "result", Parameter
.Modifier
.NONE
, null, Location
),
237 TypeManager
.iasyncresult_type
);
240 // Create method, define parameters, register parameters with type system
242 EndInvokeBuilder
= new Method (this, null, ReturnType
, MethodModifiers
, new MemberName ("EndInvoke"), end_parameters
, null);
243 EndInvokeBuilder
.Define ();
246 public override void DefineConstants ()
248 if (!Parameters
.IsEmpty
&& Parameters
[Parameters
.Count
- 1].HasDefaultValue
) {
249 var rc
= new ResolveContext (this);
250 Parameters
.ResolveDefaultValues (rc
);
254 public override void EmitType ()
256 if (ReturnType
.Type
== InternalType
.Dynamic
) {
257 return_attributes
= new ReturnParameter (this, InvokeBuilder
.MethodBuilder
, Location
);
258 PredefinedAttributes
.Get
.Dynamic
.EmitAttribute (return_attributes
.Builder
);
260 var trans_flags
= TypeManager
.HasDynamicTypeUsed (ReturnType
.Type
);
261 if (trans_flags
!= null) {
262 var pa
= PredefinedAttributes
.Get
.DynamicTransform
;
263 if (pa
.Constructor
!= null || pa
.ResolveConstructor (Location
, ArrayContainer
.MakeType (TypeManager
.bool_type
))) {
264 return_attributes
= new ReturnParameter (this, InvokeBuilder
.MethodBuilder
, Location
);
265 return_attributes
.Builder
.SetCustomAttribute (
266 new CustomAttributeBuilder (pa
.Constructor
, new object [] { trans_flags }
));
271 Parameters
.ApplyAttributes (InvokeBuilder
.MethodBuilder
);
273 Constructor
.ConstructorBuilder
.SetImplementationFlags (MethodImplAttributes
.Runtime
);
274 InvokeBuilder
.MethodBuilder
.SetImplementationFlags (MethodImplAttributes
.Runtime
);
276 if (BeginInvokeBuilder
!= null) {
277 BeginInvokeBuilder
.ParameterInfo
.ApplyAttributes (BeginInvokeBuilder
.MethodBuilder
);
279 BeginInvokeBuilder
.MethodBuilder
.SetImplementationFlags (MethodImplAttributes
.Runtime
);
280 EndInvokeBuilder
.MethodBuilder
.SetImplementationFlags (MethodImplAttributes
.Runtime
);
283 if (OptAttributes
!= null) {
284 OptAttributes
.Emit ();
290 protected override TypeExpr
[] ResolveBaseTypes (out TypeExpr base_class
)
292 base_type
= TypeManager
.multicast_delegate_type
;
297 protected override TypeAttributes TypeAttr
{
299 return ModifiersExtensions
.TypeAttr (ModFlags
, IsTopLevel
) |
300 TypeAttributes
.Class
| TypeAttributes
.Sealed
|
305 public override string[] ValidAttributeTargets
{
307 return attribute_targets
;
312 protected override bool VerifyClsCompliance ()
314 if (!base.VerifyClsCompliance ()) {
318 Parameters
.VerifyClsCompliance (this);
320 if (!ReturnType
.Type
.IsCLSCompliant ()) {
321 Report
.Warning (3002, 1, Location
, "Return type of `{0}' is not CLS-compliant",
322 GetSignatureForError ());
328 public static MethodSpec
GetConstructor (CompilerContext ctx
, TypeSpec container_type
, TypeSpec delType
)
330 var ctor
= MemberCache
.FindMember (delType
, MemberFilter
.Constructor (null), BindingRestriction
.DeclaredOnly
);
331 return (MethodSpec
) ctor
;
335 // Returns the "Invoke" from a delegate type
337 public static MethodSpec
GetInvokeMethod (CompilerContext ctx
, TypeSpec delType
)
339 var invoke
= MemberCache
.FindMember (delType
,
340 MemberFilter
.Method (InvokeMethodName
, 0, null, null),
341 BindingRestriction
.DeclaredOnly
);
343 return (MethodSpec
) invoke
;
346 public static AParametersCollection
GetParameters (CompilerContext ctx
, TypeSpec delType
)
348 var invoke_mb
= GetInvokeMethod (ctx
, delType
);
349 return invoke_mb
.Parameters
;
353 // 15.2 Delegate compatibility
355 public static bool IsTypeCovariant (Expression a
, TypeSpec b
)
358 // For each value parameter (a parameter with no ref or out modifier), an
359 // identity conversion or implicit reference conversion exists from the
360 // parameter type in D to the corresponding parameter type in M
365 if (RootContext
.Version
== LanguageVersion
.ISO_1
)
368 return Convert
.ImplicitReferenceConversionExists (a
, b
);
371 public static string FullDelegateDesc (MethodSpec invoke_method
)
373 return TypeManager
.GetFullNameSignature (invoke_method
).Replace (".Invoke", "");
376 public Expression InstanceExpression
{
378 return instance_expr
;
381 instance_expr
= value;
387 // Base class for `NewDelegate' and `ImplicitDelegateCreation'
389 public abstract class DelegateCreation
: Expression
, MethodGroupExpr
.IErrorHandler
391 protected MethodSpec constructor_method
;
392 protected MethodGroupExpr method_group
;
394 public static Arguments
CreateDelegateMethodArguments (AParametersCollection pd
, TypeSpec
[] types
, Location loc
)
396 Arguments delegate_arguments
= new Arguments (pd
.Count
);
397 for (int i
= 0; i
< pd
.Count
; ++i
) {
398 Argument
.AType atype_modifier
;
399 switch (pd
.FixedParameters
[i
].ModFlags
) {
400 case Parameter
.Modifier
.REF
:
401 atype_modifier
= Argument
.AType
.Ref
;
403 case Parameter
.Modifier
.OUT
:
404 atype_modifier
= Argument
.AType
.Out
;
411 delegate_arguments
.Add (new Argument (new TypeExpression (types
[i
], loc
), atype_modifier
));
414 return delegate_arguments
;
417 public override Expression
CreateExpressionTree (ResolveContext ec
)
419 MemberAccess ma
= new MemberAccess (new MemberAccess (new QualifiedAliasMember ("global", "System", loc
), "Delegate", loc
), "CreateDelegate", loc
);
421 Arguments args
= new Arguments (3);
422 args
.Add (new Argument (new TypeOf (new TypeExpression (type
, loc
), loc
)));
423 args
.Add (new Argument (new NullLiteral (loc
)));
424 args
.Add (new Argument (method_group
.CreateExpressionTree (ec
)));
425 Expression e
= new Invocation (ma
, args
).Resolve (ec
);
429 e
= Convert
.ExplicitConversion (ec
, e
, type
, loc
);
433 return e
.CreateExpressionTree (ec
);
436 protected override Expression
DoResolve (ResolveContext ec
)
438 constructor_method
= Delegate
.GetConstructor (ec
.Compiler
, ec
.CurrentType
, type
);
440 var invoke_method
= Delegate
.GetInvokeMethod (ec
.Compiler
, type
);
441 method_group
.DelegateType
= type
;
442 method_group
.CustomErrorHandler
= this;
444 Arguments arguments
= CreateDelegateMethodArguments (invoke_method
.Parameters
, invoke_method
.Parameters
.Types
, loc
);
445 method_group
= method_group
.OverloadResolve (ec
, ref arguments
, false, loc
);
446 if (method_group
== null)
449 var delegate_method
= method_group
.BestCandidate
;
451 if (TypeManager
.IsNullableType (delegate_method
.DeclaringType
)) {
452 ec
.Report
.Error (1728, loc
, "Cannot create delegate from method `{0}' because it is a member of System.Nullable<T> type",
453 delegate_method
.GetSignatureForError ());
457 Invocation
.IsSpecialMethodInvocation (ec
, delegate_method
, loc
);
459 ExtensionMethodGroupExpr emg
= method_group
as ExtensionMethodGroupExpr
;
461 method_group
.InstanceExpression
= emg
.ExtensionExpression
;
462 TypeSpec e_type
= emg
.ExtensionExpression
.Type
;
463 if (TypeManager
.IsValueType (e_type
)) {
464 ec
.Report
.Error (1113, loc
, "Extension method `{0}' of value type `{1}' cannot be used to create delegates",
465 delegate_method
.GetSignatureForError (), TypeManager
.CSharpName (e_type
));
469 TypeSpec rt
= delegate_method
.ReturnType
;
470 Expression ret_expr
= new TypeExpression (rt
, loc
);
471 if (!Delegate
.IsTypeCovariant (ret_expr
, invoke_method
.ReturnType
)) {
472 Error_ConversionFailed (ec
, delegate_method
, ret_expr
);
475 if (delegate_method
.IsConditionallyExcluded (loc
)) {
476 ec
.Report
.SymbolRelatedToPreviousError (delegate_method
);
477 MethodOrOperator m
= delegate_method
.MemberDefinition
as MethodOrOperator
;
478 if (m
!= null && m
.IsPartialDefinition
) {
479 ec
.Report
.Error (762, loc
, "Cannot create delegate from partial method declaration `{0}'",
480 delegate_method
.GetSignatureForError ());
482 ec
.Report
.Error (1618, loc
, "Cannot create delegate with `{0}' because it has a Conditional attribute",
483 TypeManager
.CSharpSignature (delegate_method
));
487 var expr
= method_group
.InstanceExpression
;
488 if (expr
!= null && (expr
.Type
.IsGenericParameter
|| !TypeManager
.IsReferenceType (expr
.Type
)))
489 method_group
.InstanceExpression
= new BoxedCast (expr
, TypeManager
.object_type
);
491 eclass
= ExprClass
.Value
;
495 public override void Emit (EmitContext ec
)
497 if (method_group
.InstanceExpression
== null)
498 ec
.Emit (OpCodes
.Ldnull
);
500 method_group
.InstanceExpression
.Emit (ec
);
502 var delegate_method
= method_group
.BestCandidate
;
504 // Any delegate must be sealed
505 if (!delegate_method
.DeclaringType
.IsDelegate
&& delegate_method
.IsVirtual
&& !method_group
.IsBase
) {
506 ec
.Emit (OpCodes
.Dup
);
507 ec
.Emit (OpCodes
.Ldvirtftn
, delegate_method
);
509 ec
.Emit (OpCodes
.Ldftn
, delegate_method
);
512 ec
.Emit (OpCodes
.Newobj
, constructor_method
);
515 void Error_ConversionFailed (ResolveContext ec
, MethodSpec method
, Expression return_type
)
517 var invoke_method
= Delegate
.GetInvokeMethod (ec
.Compiler
, type
);
518 string member_name
= method_group
.InstanceExpression
!= null ?
519 Delegate
.FullDelegateDesc (method
) :
520 TypeManager
.GetFullNameSignature (method
);
522 ec
.Report
.SymbolRelatedToPreviousError (type
);
523 ec
.Report
.SymbolRelatedToPreviousError (method
);
524 if (RootContext
.Version
== LanguageVersion
.ISO_1
) {
525 ec
.Report
.Error (410, loc
, "A method or delegate `{0} {1}' parameters and return type must be same as delegate `{2} {3}' parameters and return type",
526 TypeManager
.CSharpName (method
.ReturnType
), member_name
,
527 TypeManager
.CSharpName (invoke_method
.ReturnType
), Delegate
.FullDelegateDesc (invoke_method
));
530 if (return_type
== null) {
531 ec
.Report
.Error (123, loc
, "A method or delegate `{0}' parameters do not match delegate `{1}' parameters",
532 member_name
, Delegate
.FullDelegateDesc (invoke_method
));
536 ec
.Report
.Error (407, loc
, "A method or delegate `{0} {1}' return type does not match delegate `{2} {3}' return type",
537 return_type
.GetSignatureForError (), member_name
,
538 TypeManager
.CSharpName (invoke_method
.ReturnType
), Delegate
.FullDelegateDesc (invoke_method
));
541 public static bool ImplicitStandardConversionExists (ResolveContext ec
, MethodGroupExpr mg
, TypeSpec target_type
)
543 if (target_type
== TypeManager
.delegate_type
|| target_type
== TypeManager
.multicast_delegate_type
)
546 mg
.DelegateType
= target_type
;
547 var invoke
= Delegate
.GetInvokeMethod (ec
.Compiler
, target_type
);
549 Arguments arguments
= CreateDelegateMethodArguments (invoke
.Parameters
, invoke
.Parameters
.Types
, mg
.Location
);
550 return mg
.OverloadResolve (ec
, ref arguments
, true, mg
.Location
) != null;
553 #region IErrorHandler Members
555 public bool NoExactMatch (ResolveContext ec
, MethodSpec method
)
557 if (method
.IsGeneric
)
560 Error_ConversionFailed (ec
, method
, null);
564 public bool AmbiguousCall (ResolveContext ec
, MethodSpec ambiguous
)
573 // Created from the conversion code
575 public class ImplicitDelegateCreation
: DelegateCreation
577 ImplicitDelegateCreation (TypeSpec t
, MethodGroupExpr mg
, Location l
)
580 this.method_group
= mg
;
584 static public Expression
Create (ResolveContext ec
, MethodGroupExpr mge
,
585 TypeSpec target_type
, Location loc
)
587 ImplicitDelegateCreation d
= new ImplicitDelegateCreation (target_type
, mge
, loc
);
588 return d
.DoResolve (ec
);
593 // A delegate-creation-expression, invoked from the `New' class
595 public class NewDelegate
: DelegateCreation
597 public Arguments Arguments
;
600 // This constructor is invoked from the `New' expression
602 public NewDelegate (TypeSpec type
, Arguments Arguments
, Location loc
)
605 this.Arguments
= Arguments
;
609 protected override Expression
DoResolve (ResolveContext ec
)
611 if (Arguments
== null || Arguments
.Count
!= 1) {
612 ec
.Report
.Error (149, loc
, "Method name expected");
616 Argument a
= Arguments
[0];
617 if (!a
.ResolveMethodGroup (ec
))
620 Expression e
= a
.Expr
;
622 AnonymousMethodExpression ame
= e
as AnonymousMethodExpression
;
623 if (ame
!= null && RootContext
.Version
!= LanguageVersion
.ISO_1
) {
624 e
= ame
.Compatible (ec
, type
);
628 return e
.Resolve (ec
);
631 method_group
= e
as MethodGroupExpr
;
632 if (method_group
== null) {
633 if (e
.Type
== InternalType
.Dynamic
) {
634 e
= Convert
.ImplicitConversionRequired (ec
, e
, type
, loc
);
635 } else if (!e
.Type
.IsDelegate
) {
636 e
.Error_UnexpectedKind (ec
, ResolveFlags
.MethodGroup
| ResolveFlags
.Type
, loc
);
641 // An argument is not a method but another delegate
643 method_group
= new MethodGroupExpr (Delegate
.GetInvokeMethod (ec
.Compiler
, e
.Type
), e
.Type
, loc
);
644 method_group
.InstanceExpression
= e
;
647 return base.DoResolve (ec
);
652 // Invocation converted to delegate Invoke call
654 class DelegateInvocation
: ExpressionStatement
656 readonly Expression InstanceExpr
;
660 public DelegateInvocation (Expression instance_expr
, Arguments args
, Location loc
)
662 this.InstanceExpr
= instance_expr
;
663 this.arguments
= args
;
667 public override Expression
CreateExpressionTree (ResolveContext ec
)
669 Arguments args
= Arguments
.CreateForExpressionTree (ec
, this.arguments
,
670 InstanceExpr
.CreateExpressionTree (ec
));
672 return CreateExpressionFactoryCall (ec
, "Invoke", args
);
675 protected override Expression
DoResolve (ResolveContext ec
)
677 if (InstanceExpr
is EventExpr
) {
678 ((EventExpr
) InstanceExpr
).Error_CannotAssign (ec
);
682 TypeSpec del_type
= InstanceExpr
.Type
;
683 if (del_type
== null)
686 method
= Delegate
.GetInvokeMethod (ec
.Compiler
, del_type
);
688 var me
= new MethodGroupExpr (mb
, del_type
, loc
);
689 me
.InstanceExpression
= InstanceExpr
;
691 AParametersCollection pd
= mb
.Parameters
;
692 int pd_count
= pd
.Count
;
694 int arg_count
= arguments
== null ? 0 : arguments
.Count
;
696 bool params_method
= pd
.HasParams
;
697 bool is_params_applicable
= false;
698 bool is_applicable
= me
.IsApplicable (ec
, ref arguments
, arg_count
, ref mb
, ref is_params_applicable
) == 0;
699 if (arguments
!= null)
700 arg_count
= arguments
.Count
;
702 if (!is_applicable
&& !params_method
&& arg_count
!= pd_count
) {
703 ec
.Report
.Error (1593, loc
, "Delegate `{0}' does not take `{1}' arguments",
704 TypeManager
.CSharpName (del_type
), arg_count
.ToString ());
705 } else if (arguments
== null || !arguments
.HasDynamic
) {
706 me
.VerifyArgumentsCompat (ec
, ref arguments
, arg_count
, mb
,
707 is_params_applicable
|| (!is_applicable
&& params_method
), false, loc
);
710 type
= method
.ReturnType
;
711 eclass
= ExprClass
.Value
;
715 public override void Emit (EmitContext ec
)
718 // Invocation on delegates call the virtual Invoke member
719 // so we are always `instance' calls
721 Invocation
.EmitCall (ec
, false, InstanceExpr
, method
, arguments
, loc
);
724 public override void EmitStatement (EmitContext ec
)
728 // Pop the return value if there is one
730 if (type
!= TypeManager
.void_type
)
731 ec
.Emit (OpCodes
.Pop
);
734 public override System
.Linq
.Expressions
.Expression
MakeExpression (BuilderContext ctx
)
736 return Invocation
.MakeExpression (ctx
, InstanceExpr
, method
, arguments
);