Getting started with C# LanguageVerbatim StringsOperatorsExtension MethodsCollection InitializersString InterpolationC# 6.0 FeaturesConstructors and FinalizersKeywordsGenericsReflectionInheritanceNull-Coalescing OperatorUsing StatementString Escape SequencesException HandlingNull-conditional OperatorsBuilt-in TypesLambda expressionsAsync-AwaitPropertiesThreadingUsing DirectiveMethodsYield KeywordEventsLINQ QueriesCommon String OperationsExpression TreesOverload ResolutionString.Formatnameof OperatorUnsafe Code in .NETInitializing PropertiesBindingList<T>ILGeneratorObject initializersXML Documentation CommentsPreprocessor directivesDynamic typeAnonymous typesStructsTuplesEnumAccess ModifiersTask Parallel LibraryAttributesGuidSingleton ImplementationDelegatesNullable typesGarbage Collector in .NetNetworkingArraysEquality OperatorLock StatementAction FiltersXmlDocument and the System.Xml namespaceDateTime MethodsBackgroundWorkerPolymorphismStatic ClassesIndexerIDisposable interfaceAliases of built-in typesImmutabilityXDocument and the System.Xml.Linq namespaceC# 7.0 FeaturesPerforming HTTP requestsGenerating Random Numbers in C#LoopingNamed ArgumentsDiagnosticsInterfacesIEnumerableNaming ConventionsAn overview of c# collectionsChecked and UncheckedRecursionFunctional ProgrammingLiteralsCastingNullReferenceExceptionFunc delegatesLINQ to XMLHash FunctionsHandling FormatException when converting string to other typesCryptography (System.Security.Cryptography)INotifyPropertyChanged interfaceValue type vs Reference typeC# 4.0 FeaturesIQueryable interfaceTask Parallel Library (TPL) Dataflow ConstructsStreamRuntime CompileConditional StatementsInteroperabilityOverflowEquals and GetHashCodeType ConversionParallel LINQ (PLINQ)String ManipulationString ConcatenatePartial class and methodsStopwatchesRegex ParsingC# ScriptC# 3.0 FeaturesAsync/await, Backgroundworker, Task and Thread ExamplesTimersFunction with multiple return valuesBinary SerializationMaking a variable thread safeIComparableCode ContractsIteratorsAssemblyInfo.cs ExamplesFile and Stream I/OCode Contracts and AssertionsCachingC# 5.0 FeaturesImplementing Flyweight Design PatternStringBuilderImplementing Decorator Design PatternAccessing DatabasesT4 Code GenerationMicrosoft.Exchange.WebServices.NET Compiler Platform (Roslyn)Data AnnotationUsing SQLite in C#System.Management.AutomationFileSystemWatcherSystem.DirectoryServices.Protocols.LdapConnectionNamed and Optional ArgumentsComments and regionsC# Authentication handlerPointers & Unsafe CodePointersHow to use C# Structs to create a Union type (Similar to C Unions)BigIntegerDependency InjectionReactive Extensions (Rx)Creational Design PatternsCreating a Console Application using a Plain-Text Editor and the C# Compiler (csc.exe)Reading and writing .zip filesGeneric Lambda Query BuilderImport Google ContactsLambda ExpressionsCLSCompliantAttributeObservableCollection<T>Synchronization Context in Async-AwaitICloneableRead & Understand StacktracesLinq to ObjectsASP.NET IdentityAccess network shared folder with username and passwordAsynchronous SocketStructural Design PatternsO(n) Algorithm for circular rotation of an arrayCreating Own MessageBox in Windows Form ApplicationIncluding Font ResourcesObject Oriented Programming In C#Using json.netGetting Started: Json with C#Windows Communication Foundation

Overload Resolution

Other topics

Remarks:

The process of overload resolution is described in the C# specification, section 7.5.3. Also relevant are the sections 7.5.2 (type inference) and 7.6.5 (invocation expressions).

How overload resolution works will probably be changed in C# 7. The design notes indicate that Microsoft will roll out a new system for determining which method is better (in complicated scenarios).

Basic Overloading Example

This code contains an overloaded method named Hello:

class Example
{
    public static void Hello(int arg)
    {
        Console.WriteLine("int");
    }
 
    public static void Hello(double arg)
    {
        Console.WriteLine("double");
    }
 
    public static void Main(string[] args) 
    {
        Hello(0);
        Hello(0.0);
    }
}

When the Main method is called, it will print

int
double

At compile-time, when the compiler finds the method call Hello(0), it finds all methods with the name Hello. In this case, it finds two of them. It then tries to determine which of the methods is better. The algorithm for determining which method is better is complex, but it usually boils down to "make as few implicit conversions as possible".

Thus, in the case of Hello(0), no conversion is needed for the method Hello(int) but an implicit numeric conversion is needed for the method Hello(double). Thus, the first method is chosen by the compiler.

In the case of Hello(0.0), there is no way to convert 0.0 to an int implicitly, so the method Hello(int) is not even considered for overload resolution. Only method remains and so it is chosen by the compiler.

"params" is not expanded, unless necessary.

The following program:

class Program
{
    static void Method(params Object[] objects)
    {
        System.Console.WriteLine(objects.Length);
    }   
    static void Method(Object a, Object b)
    {
        System.Console.WriteLine("two");
    }
    static void Main(string[] args)
    {
        object[] objectArray = new object[5];

        Method(objectArray);
        Method(objectArray, objectArray);
        Method(objectArray, objectArray, objectArray);
    }
}

will print:

5
two
3

The call expression Method(objectArray) could be interpreted in two ways: a single Object argument that happens to be an array (so the program would output 1 because that would be the number of arguments, or as an array of arguments, given in the normal form, as though the method Method did not have the keyword params. In these situations, the normal, non-expanded form always takes precedence. So, the program outputs 5.

In the second expression, Method(objectArray, objectArray), both the expanded form of the first method and the traditional second method are applicable. In this case also, non-expanded forms take precedence, so the program prints two.

In the third expression, Method(objectArray, objectArray, objectArray), the only option is to use the expanded form of the first method, and so the program prints 3.

Passing null as one of the arguments

If you have

void F1(MyType1 x) {
    // do something
}

void F1(MyType2 x) {
    // do something else
}

and for some reason you need to call the first overload of F1 but with x = null, then doing simply

F1(null);

will not compile as the call is ambiguous. To counter this you can do

F1(null as MyType1);

Contributors

Topic Id: 77

Example Ids: 356,357,20454

This site is not affiliated with any of the contributors.