C#idiomatic C#
how-to-use-indexed-properties-in-com-interop-programmingcsharp/advanced-topics/interop

Advanced

How to use indexed properties in COM interop programming

Learn how indexed properties improve the way C# objects consume COM properties that have parameters.

  • page csharp/advanced-topics/interop/how-to-use-indexed-properties-in-com-interop-programming
  • updated 02/15/2023

Indexed properties work together with other features in C#, such as named and optional arguments, a new type (dynamic), and embedded type information, to enhance Microsoft Office programming.


author: BillWagner ms.author: wiwagn ms.topic: include ms.date: 02/28/2023

In earlier versions of C#, methods are accessible as properties only if the get method has no parameters and the set method has one and only one value parameter. However, not all COM properties meet those restrictions. For example, the Excel Microsoft.Office.Interop.Excel.Range.Range property has a get accessor that requires a parameter for the name of the range. In the past, because you couldn't access the Range property directly, you had to use the get_Range method instead, as shown in the following example.

sample · csharpdocs/csharp/advanced-topics/interop/snippets/IndexedProperties/Program.csSnippet1

csharp
// Snippets 5000 Note:  
// The container used for building our samples doesn't include the Office assemblies.
// This sample will generate a few errors in the CI build. Those are expected,
// so the build passes.
//
// If you update this sample, make sure to build it locally.
// Then, make sure no new errors are added.

//<snippet5>
// You must add a reference to Microsoft.Office.Interop.Excel to run
// this example.
using System;
using Excel = Microsoft.Office.Interop.Excel;

namespace IndexedProperties
{
    class Program
    {
        static void Main(string[] args)
        {
            CSharp2010();
        }

        static void CSharp2010()
        {
            var excelApp = new Excel.Application();
            excelApp.Workbooks.Add();
            excelApp.Visible = true;

            Excel.Range targetRange = excelApp.Range["A1"];
            targetRange.Value = "Name";
        }

        static void CSharp2008()
        {
            var excelApp = new Excel.Application();
            excelApp.Workbooks.Add(Type.Missing);
            excelApp.Visible = true;

            Excel.Range targetRange = excelApp.get_Range("A1", Type.Missing);
            targetRange.set_Value(Type.Missing, "Name");
            // Or
            //targetRange.Value2 = "Name";
        }
    }
}
//</snippet5>

namespace IndexedPieces
{
    class Pieces
    {
        public void Snippets2008()
        {
            //<snippet1>
            // Visual C# 2008 and earlier.
            var excelApp = new Excel.Application();
            // . . .
            Excel.Range targetRange = excelApp.get_Range("A1", Type.Missing);
            //</snippet1>

        }

        public void Snippets2010()
        {
            //<snippet2>
            // Visual C# 2010.
            var excelApp = new Excel.Application();
            // . . .
            Excel.Range targetRange = excelApp.Range["A1"];
            //</snippet2>

            //<snippet4>
            // Visual C# 2010.
            targetRange.Value = "Name";
            //</snippet4>
        }
    }
}

Indexed properties enable you to write the following instead:

sample · csharpdocs/csharp/advanced-topics/interop/snippets/IndexedProperties/Program.csSnippet2

csharp
// Snippets 5000 Note:  
// The container used for building our samples doesn't include the Office assemblies.
// This sample will generate a few errors in the CI build. Those are expected,
// so the build passes.
//
// If you update this sample, make sure to build it locally.
// Then, make sure no new errors are added.

//<snippet5>
// You must add a reference to Microsoft.Office.Interop.Excel to run
// this example.
using System;
using Excel = Microsoft.Office.Interop.Excel;

namespace IndexedProperties
{
    class Program
    {
        static void Main(string[] args)
        {
            CSharp2010();
        }

        static void CSharp2010()
        {
            var excelApp = new Excel.Application();
            excelApp.Workbooks.Add();
            excelApp.Visible = true;

            Excel.Range targetRange = excelApp.Range["A1"];
            targetRange.Value = "Name";
        }

        static void CSharp2008()
        {
            var excelApp = new Excel.Application();
            excelApp.Workbooks.Add(Type.Missing);
            excelApp.Visible = true;

            Excel.Range targetRange = excelApp.get_Range("A1", Type.Missing);
            targetRange.set_Value(Type.Missing, "Name");
            // Or
            //targetRange.Value2 = "Name";
        }
    }
}
//</snippet5>

namespace IndexedPieces
{
    class Pieces
    {
        public void Snippets2008()
        {
            //<snippet1>
            // Visual C# 2008 and earlier.
            var excelApp = new Excel.Application();
            // . . .
            Excel.Range targetRange = excelApp.get_Range("A1", Type.Missing);
            //</snippet1>

        }

        public void Snippets2010()
        {
            //<snippet2>
            // Visual C# 2010.
            var excelApp = new Excel.Application();
            // . . .
            Excel.Range targetRange = excelApp.Range["A1"];
            //</snippet2>

            //<snippet4>
            // Visual C# 2010.
            targetRange.Value = "Name";
            //</snippet4>
        }
    }
}

The previous example also uses the optional arguments feature, which enables you to omit Type.Missing.

Indexed properties enable you to write the following code.

sample · csharpdocs/csharp/advanced-topics/interop/snippets/IndexedProperties/Program.csSnippet4

csharp
// Snippets 5000 Note:  
// The container used for building our samples doesn't include the Office assemblies.
// This sample will generate a few errors in the CI build. Those are expected,
// so the build passes.
//
// If you update this sample, make sure to build it locally.
// Then, make sure no new errors are added.

//<snippet5>
// You must add a reference to Microsoft.Office.Interop.Excel to run
// this example.
using System;
using Excel = Microsoft.Office.Interop.Excel;

namespace IndexedProperties
{
    class Program
    {
        static void Main(string[] args)
        {
            CSharp2010();
        }

        static void CSharp2010()
        {
            var excelApp = new Excel.Application();
            excelApp.Workbooks.Add();
            excelApp.Visible = true;

            Excel.Range targetRange = excelApp.Range["A1"];
            targetRange.Value = "Name";
        }

        static void CSharp2008()
        {
            var excelApp = new Excel.Application();
            excelApp.Workbooks.Add(Type.Missing);
            excelApp.Visible = true;

            Excel.Range targetRange = excelApp.get_Range("A1", Type.Missing);
            targetRange.set_Value(Type.Missing, "Name");
            // Or
            //targetRange.Value2 = "Name";
        }
    }
}
//</snippet5>

namespace IndexedPieces
{
    class Pieces
    {
        public void Snippets2008()
        {
            //<snippet1>
            // Visual C# 2008 and earlier.
            var excelApp = new Excel.Application();
            // . . .
            Excel.Range targetRange = excelApp.get_Range("A1", Type.Missing);
            //</snippet1>

        }

        public void Snippets2010()
        {
            //<snippet2>
            // Visual C# 2010.
            var excelApp = new Excel.Application();
            // . . .
            Excel.Range targetRange = excelApp.Range["A1"];
            //</snippet2>

            //<snippet4>
            // Visual C# 2010.
            targetRange.Value = "Name";
            //</snippet4>
        }
    }
}

You can't create indexed properties of your own. The feature only supports consumption of existing indexed properties.

Example

The following code shows a complete example. For more information about how to set up a project that accesses the Office API, see How to access Office interop objects by using C# features.

sample · csharpdocs/csharp/advanced-topics/interop/snippets/IndexedProperties/Program.csSnippet5

csharp
// Snippets 5000 Note:  
// The container used for building our samples doesn't include the Office assemblies.
// This sample will generate a few errors in the CI build. Those are expected,
// so the build passes.
//
// If you update this sample, make sure to build it locally.
// Then, make sure no new errors are added.

//<snippet5>
// You must add a reference to Microsoft.Office.Interop.Excel to run
// this example.
using System;
using Excel = Microsoft.Office.Interop.Excel;

namespace IndexedProperties
{
    class Program
    {
        static void Main(string[] args)
        {
            CSharp2010();
        }

        static void CSharp2010()
        {
            var excelApp = new Excel.Application();
            excelApp.Workbooks.Add();
            excelApp.Visible = true;

            Excel.Range targetRange = excelApp.Range["A1"];
            targetRange.Value = "Name";
        }

        static void CSharp2008()
        {
            var excelApp = new Excel.Application();
            excelApp.Workbooks.Add(Type.Missing);
            excelApp.Visible = true;

            Excel.Range targetRange = excelApp.get_Range("A1", Type.Missing);
            targetRange.set_Value(Type.Missing, "Name");
            // Or
            //targetRange.Value2 = "Name";
        }
    }
}
//</snippet5>

namespace IndexedPieces
{
    class Pieces
    {
        public void Snippets2008()
        {
            //<snippet1>
            // Visual C# 2008 and earlier.
            var excelApp = new Excel.Application();
            // . . .
            Excel.Range targetRange = excelApp.get_Range("A1", Type.Missing);
            //</snippet1>

        }

        public void Snippets2010()
        {
            //<snippet2>
            // Visual C# 2010.
            var excelApp = new Excel.Application();
            // . . .
            Excel.Range targetRange = excelApp.Range["A1"];
            //</snippet2>

            //<snippet4>
            // Visual C# 2010.
            targetRange.Value = "Name";
            //</snippet4>
        }
    }
}

See also