1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4 
5 using System.Collections.Generic;
6 using System.Collections.ObjectModel;
7 using System.Dynamic.Utils;
8 
9 namespace System.Dynamic
10 {
11     /// <summary>
12     /// Describes arguments in the dynamic binding process.
13     /// </summary>
14     /// <remarks>
15     /// <see cref="ArgumentCount"/> - all inclusive number of arguments.
16     /// <see cref="ArgumentNames"/> - names for those arguments that are named.
17     ///
18     /// Argument names match to the argument values in left to right order
19     /// and last name corresponds to the last argument.
20     /// </remarks>
21     /// <example>
22     /// <code>
23     ///   Foo(arg1, arg2, arg3, name1 = arg4, name2 = arg5, name3 = arg6)
24     /// </code>
25     ///   will correspond to
26     /// <code>
27     ///   new CallInfo(6, "name1", "name2", "name3")
28     /// </code>
29     /// </example>
30     public sealed class CallInfo
31     {
32         /// <summary>
33         /// Creates a new <see cref="CallInfo"/> that represents arguments in the dynamic binding process.
34         /// </summary>
35         /// <param name="argCount">The number of arguments.</param>
36         /// <param name="argNames">The argument names.</param>
37         /// <returns>The new <see cref="CallInfo"/> instance.</returns>
CallInfo(int argCount, params string[] argNames)38         public CallInfo(int argCount, params string[] argNames)
39             : this(argCount, (IEnumerable<string>)argNames)
40         {
41         }
42 
43         /// <summary>
44         /// Creates a new <see cref="CallInfo"/> that represents arguments in the dynamic binding process.
45         /// </summary>
46         /// <param name="argCount">The number of arguments.</param>
47         /// <param name="argNames">The argument names.</param>
48         /// <returns>The new <see cref="CallInfo"/> instance.</returns>
CallInfo(int argCount, IEnumerable<string> argNames)49         public CallInfo(int argCount, IEnumerable<string> argNames)
50         {
51             ContractUtils.RequiresNotNull(argNames, nameof(argNames));
52 
53             var argNameCol = argNames.ToReadOnly();
54 
55             if (argCount < argNameCol.Count) throw System.Linq.Expressions.Error.ArgCntMustBeGreaterThanNameCnt();
56             ContractUtils.RequiresNotNullItems(argNameCol, nameof(argNames));
57 
58             ArgumentCount = argCount;
59             ArgumentNames = argNameCol;
60         }
61 
62         /// <summary>
63         /// The number of arguments.
64         /// </summary>
65         public int ArgumentCount { get; }
66 
67         /// <summary>
68         /// The argument names.
69         /// </summary>
70         public ReadOnlyCollection<string> ArgumentNames { get; }
71 
72         /// <summary>
73         /// Serves as a hash function for the current <see cref="CallInfo"/>.
74         /// </summary>
75         /// <returns>A hash code for the current <see cref="CallInfo"/>.</returns>
GetHashCode()76         public override int GetHashCode()
77         {
78             return ArgumentCount ^ ArgumentNames.ListHashCode();
79         }
80 
81         /// <summary>
82         /// Determines whether the specified <see cref="CallInfo"/> instance is considered equal to the current instance.
83         /// </summary>
84         /// <param name="obj">The instance of <see cref="CallInfo"/> to compare with the current instance.</param>
85         /// <returns>true if the specified instance is equal to the current one otherwise, false.</returns>
Equals(object obj)86         public override bool Equals(object obj)
87         {
88             var other = obj as CallInfo;
89             return other != null && ArgumentCount == other.ArgumentCount && ArgumentNames.ListEquals(other.ArgumentNames);
90         }
91     }
92 }
93