diff --git a/.openpublishing.redirection.csharp.json b/.openpublishing.redirection.csharp.json index 684092eec0dee..2a4cc85d877fe 100644 --- a/.openpublishing.redirection.csharp.json +++ b/.openpublishing.redirection.csharp.json @@ -4042,12 +4042,12 @@ }, { "source_path_from_root": "/docs/csharp/quick-starts/interpolated-strings-local.md", - "redirect_url": "/dotnet/csharp/tutorials/exploration/interpolated-strings-local", - "redirect_document_id": true + "redirect_url": "/dotnet/csharp/tutorials/string-interpolation" }, { - "source_path_from_root": "/docs/csharp/quick-starts/interpolated-strings.md", - "redirect_url": "/dotnet/csharp/tutorials/exploration/interpolated-strings" + "source_path_from_root": "/docs/csharp/quick-starts/interpolated-strings.yml", + "redirect_url": "/dotnet/csharp/tutorials/string-interpolation", + "redirect_document_id": true }, { "source_path_from_root": "/docs/csharp/quick-starts/introduction-to-classes.md", @@ -4060,7 +4060,7 @@ }, { "source_path_from_root": "/docs/csharp/quick-starts/local-environment.md", - "redirect_url": "/dotnet/csharp/tour-of-csharp/tutorials", + "redirect_url": "/dotnet/csharp/tour-of-csharp/tutorials/", "redirect_document_id": true }, { @@ -4208,6 +4208,14 @@ "source_path_from_root": "/docs/csharp/tutorials/exploration/top-level-statements.md", "redirect_url": "/dotnet/csharp/tutorials/top-level-statements" }, + { + "source_path_from_root": "/docs/csharp/tutorials/exploration/interpolated-strings-local.md", + "redirect_url": "/dotnet/csharp/tutorials/string-interpolation" + }, + { + "source_path_from_root": "/docs/csharp/tutorials/exploration/interpolated-strings.yml", + "redirect_url": "/dotnet/csharp/tutorials/string-interpolation" + }, { "source_path_from_root": "/docs/csharp/tutorials/generate-consume-asynchronous-stream.md", "redirect_url": "/dotnet/csharp/asynchronous-programming/generate-consume-asynchronous-stream" @@ -4242,11 +4250,11 @@ }, { "source_path_from_root": "/docs/csharp/tutorials/intro-to-csharp/interpolated-strings-local.md", - "redirect_url": "/dotnet/csharp/tutorials/exploration/interpolated-strings-local" + "redirect_url": "/dotnet/csharp/tutorials/interpolated-strings" }, { "source_path_from_root": "/docs/csharp/tutorials/intro-to-csharp/interpolated-strings.yml", - "redirect_url": "/dotnet/csharp/tutorials/exploration/interpolated-strings" + "redirect_url": "/dotnet/csharp/tutorials/interpolated-strings" }, { "source_path_from_root": "/docs/csharp/tutorials/intro-to-csharp/introduction-to-classes.md", diff --git a/docs/ai/get-started-mcp.md b/docs/ai/get-started-mcp.md new file mode 100644 index 0000000000000..ffc03b0b31a44 --- /dev/null +++ b/docs/ai/get-started-mcp.md @@ -0,0 +1,100 @@ +--- +title: Get started with .NET AI and MCP +description: Learn about .NET AI and MCP key concepts and development resources to get started building MCP clients and servers +ms.date: 04/29/2025 +ms.topic: overview +ms.custom: devx-track-dotnet, devx-track-dotnet-ai +author: alexwolfmsft +ms.author: alexwolf +# CustomerIntent: As a .NET developer new to OpenAI, I want deploy and use sample code to interact to learn from the sample code to summarize text. +--- + +# Get started with .NET AI and the Model Context Protocol + +The Model Context Protocol (MCP) is an open protocol designed to standardize integrations between AI apps and external tools and data sources. By using MCP, developers can enhance the capabilities of AI models, enabling them to produce more accurate, relevant, and context-aware responses. + +For example, using MCP, you can connect your LLM to resources such as: + +- Document databases or storage services. +- Web APIs that expose business data or logic. +- Tools that manage files or performing local tasks on a user's device. + +Many Microsoft products already support MCP, including: + +- [Copilot Studio](https://www.microsoft.com/microsoft-copilot/blog/copilot-studio/introducing-model-context-protocol-mcp-in-copilot-studio-simplified-integration-with-ai-apps-and-agents/) +- [Visual Studio Code GitHub Copilot agent mode](https://code.visualstudio.com/blogs/2025/02/24/introducing-copilot-agent-mode) +- [Semantic Kernel](https://devblogs.microsoft.com/semantic-kernel/integrating-model-context-protocol-tools-with-semantic-kernel-a-step-by-step-guide/). + +You can use the [MCP C# SDK](#develop-with-the-mcp-c-sdk) to quickly create your own MCP integrations and switch between different AI models without significant code changes. + +### MCP client-server architecture + +MCP uses a client-server architecture that enables an AI-powered app (the host) to connect to multiple MCP servers through MCP clients: + +- **MCP Hosts**: AI tools, code editors, or other software that enhance their AI models using contextual resources through MCP. For example, GitHub Copilot in Visual Studio Code can act as an MCP host and use MCP clients and servers to expand its capabilities. +- **MCP Clients**: Clients used by the host application to connect to MCP servers to retrieve contextual data. +- **MCP Servers**: Services that expose capabilities to clients through MCP. For example, an MCP server might provide an abstraction over a REST API or local data source to provide business data to the AI model. + +The following diagram illustrates this architecture: + +:::image type="content" source="media/mcp/model-context-protocol-architecture-diagram.png" alt-text="A diagram showing the architecture pattern of MCP, including hosts, clients, and servers."::: + +MCP client and server can exchange a set of standard messages: + +| Message | Description | +|---------------------|-------------| +| `InitializeRequest` | This request is sent by the client to the server when it first connects, asking it to begin initialization. | +|`ListToolsRequest` | Sent by the client to request a list of tools the server has. | +|`CallToolRequest` | Used by the client to invoke a tool provided by the server. | +|`ListResourcesRequest` | Sent by the client to request a list of available server resources. | +|`ReadResourceRequest` | Sent by the client to the server to read a specific resource URI. | +|`ListPromptsRequest` | Sent by the client to request a list of available prompts and prompt templates from the server. | +|`GetPromptRequest` | Used by the client to get a prompt provided by the server. | +|`PingRequest` | A ping, issued by either the server or the client, to check that the other party is still alive. | +|`CreateMessageRequest` | A request by the server to sample an LLM via the client. The client has full discretion over which model to select. The client should also inform the user before beginning sampling, to allow them to inspect the request (human in the loop) and decide whether to approve it. | +|`SetLevelRequest` | A request by the client to the server, to enable or adjust logging. | + +## Develop with the MCP C# SDK + +As a .NET developer, you can use MCP by creating MCP clients and servers to enhance your apps with custom integrations. MCP reduces the complexity involved in connecting an AI model to various tools, services, and data sources. + +The official [MCP C# SDK](https://github.com/modelcontextprotocol/csharp-sdk) is available through NuGet and enables you to build MCP clients and servers for .NET apps and libraries. The SDK is maintained through collaboration between Microsoft, Anthropic, and the MCP open protocol organization. + +To get started, add the MCP C# SDK to your project: + +```dotnetcli +dotnet add package ModelContextProtocol --prerelease +``` + +Instead of building unique connectors for each integration point, you can often leverage or reference prebuilt integrations from various providers such as GitHub and Docker: + +- [Available MPC clients](https://modelcontextprotocol.io/clients) +- [Available MCP servers](https://modelcontextprotocol.io/examples) + +### Integration with Microsoft.Extensions.AI + +The MCP C# SDK depends on the [Microsoft.Extensions.AI libraries](/dotnet/ai/ai-extensions) to handle various AI interactions and tasks. These extension libraries provides core types and abstractions for working with AI services, so developers can focus on coding against conceptual AI capabilities rather than specific platforms or provider implementations. + +View the MCP C# SDK dependencies on the [NuGet package page](https://www.nuget.org/packages/ModelContextProtocol/0.1.0-preview.11). + +## More .NET MCP development resources + +Various tools, services, and learning resources are available in the .NET and Azure ecosystems to help you build MCP clients and servers or integrate with existing MCP servers. + +Get started with the following development tools: + +- [Semantic Kernel](/semantic-kernel/concepts/plugins/adding-mcp-plugins) allows you to add plugins for MCP servers. Semantic Kernel supports both local MCP servers through standard I/O and remote servers that connect through SSE over HTTPS. +- [Azure Functions remote MCP servers](https://devblogs.microsoft.com/dotnet/build-mcp-remote-servers-with-azure-functions/) combine MCP standards with the flexible architecture of Azure Functions. Visit the [Remote MCP functions sample repository](https://aka.ms/cadotnet/mcp/functions/remote-sample) for code examples. +- [Azure MCP Server](https://github.com/Azure/azure-mcp) implements the MCP specification to seamlessly connect AI agents with key Azure services like Azure Storage, Cosmos DB, and more. + +Learn more about .NET and MCP using these resources: + +- [Microsoft partners with Anthropic to create official C# SDK for Model Context Protocol](https://devblogs.microsoft.com/blog/microsoft-partners-with-anthropic-to-create-official-c-sdk-for-model-context-protocol) +- [Build a Model Context Protocol (MCP) server in C#](https://devblogs.microsoft.com/dotnet/build-a-model-context-protocol-mcp-server-in-csharp/) +- [MCP C# SDK README](https://github.com/modelcontextprotocol/csharp-sdk/blob/main/README.md) + +## Related content + +- [Overview of the .NET + AI ecosystem](/dotnet/ai/dotnet-ai-ecosystem) +- [Microsoft.Extensions.AI](/dotnet/ai/ai-extensions) +- [Semantic Kernel overview for .NET](/dotnet/ai/semantic-kernel-dotnet-overview) diff --git a/docs/ai/index.yml b/docs/ai/index.yml index fefbd4ebfdecf..9223c4d8e1a63 100644 --- a/docs/ai/index.yml +++ b/docs/ai/index.yml @@ -21,20 +21,20 @@ landingContent: # Card - title: Get started linkLists: - - linkListType: get-started + - linkListType: overview links: - text: Develop .NET apps with AI features url: overview.md - - text: Connect to and prompt an AI model - url: quickstarts/prompt-model.md - text: Microsoft.Extensions.AI libraries url: microsoft-extensions-ai.md + - linkListType: get-started + links: + - text: Connect to and prompt an AI model + url: quickstarts/prompt-model.md - text: Build an Azure AI chat app - url: quickstarts/get-started-openai.md - - text: Summarize text using an Azure OpenAI chat app - url: quickstarts/quickstart-openai-summarize-text.md + url: quickstarts/build-chat-app.md - text: Generate images using Azure AI - url: quickstarts/quickstart-openai-generate-images.md + url: quickstarts/generate-images.md # Card - title: Essential concepts diff --git a/docs/ai/media/mcp/model-context-protocol-architecture-diagram.png b/docs/ai/media/mcp/model-context-protocol-architecture-diagram.png new file mode 100644 index 0000000000000..e6967110454e3 Binary files /dev/null and b/docs/ai/media/mcp/model-context-protocol-architecture-diagram.png differ diff --git a/docs/ai/quickstarts/evaluate-ai-response.md b/docs/ai/quickstarts/evaluate-ai-response.md index 97630751d4e30..7373ac005f6b9 100644 --- a/docs/ai/quickstarts/evaluate-ai-response.md +++ b/docs/ai/quickstarts/evaluate-ai-response.md @@ -11,7 +11,9 @@ ms.custom: devx-track-dotnet, devx-track-dotnet-ai In this quickstart, you create an MSTest app to evaluate the chat response of an OpenAI model. The test app uses the [Microsoft.Extensions.AI.Evaluation](https://www.nuget.org/packages/Microsoft.Extensions.AI.Evaluation) libraries. > [!NOTE] -> This quickstart demonstrates the simplest usage of the evaluation API. Notably, it doesn't demonstrate use of the [response caching](../conceptual/evaluation-libraries.md#cached-responses) and [reporting](../conceptual/evaluation-libraries.md#reporting) functionality, which are important if you're authoring unit tests that run as part of an "offline" evaluation pipeline. The scenario shown in this quickstart is suitable in use cases such as "online" evaluation of AI responses within production code and logging scores to telemetry, where caching and reporting aren't relevant. For a tutorial that demonstrates the caching and reporting functionality, see [Tutorial: Evaluate a model's response with response caching and reporting](../tutorials/evaluate-with-reporting.md) +> +> - The `Microsoft.Extensions.AI.Evaluation` library is currently in Preview. +> - This quickstart demonstrates the simplest usage of the evaluation API. Notably, it doesn't demonstrate use of the [response caching](../conceptual/evaluation-libraries.md#cached-responses) and [reporting](../conceptual/evaluation-libraries.md#reporting) functionality, which are important if you're authoring unit tests that run as part of an "offline" evaluation pipeline. The scenario shown in this quickstart is suitable in use cases such as "online" evaluation of AI responses within production code and logging scores to telemetry, where caching and reporting aren't relevant. For a tutorial that demonstrates the caching and reporting functionality, see [Tutorial: Evaluate a model's response with response caching and reporting](../tutorials/evaluate-with-reporting.md) ## Prerequisites diff --git a/docs/ai/quickstarts/generate-images.md b/docs/ai/quickstarts/generate-images.md index a14010a8d0c35..523948bb2bc94 100644 --- a/docs/ai/quickstarts/generate-images.md +++ b/docs/ai/quickstarts/generate-images.md @@ -98,7 +98,7 @@ Complete the following steps to create a .NET console app to connect to an AI mo ## Add the app code -1. In the **Program.cs** file, add the following code to connect and authenticate to the AI model. +1. In the `Program.cs` file, add the following code to connect and authenticate to the AI model. :::zone target="docs" pivot="azure-openai" @@ -117,12 +117,12 @@ Complete the following steps to create a .NET console app to connect to an AI mo The preceding code: - - Reads essential configuration values from the project user secrets to connect to the AI model - - Creates an `ImageClient` to connect to the AI model - - Sends a prompt to the model that describes the desired image - - Prints the URL of the generated image to the console output + - Reads essential configuration values from the project user secrets to connect to the AI model. + - Creates an `OpenAI.Images.ImageClient` to connect to the AI model. + - Sends a prompt to the model that describes the desired image. + - Prints the URL of the generated image to the console output. -1. Use the `dotnet run` command to run the app: +1. Run the app: ```dotnetcli dotnet run diff --git a/docs/ai/quickstarts/includes/clone-sample-repo.md b/docs/ai/quickstarts/includes/clone-sample-repo.md index 4a9c2d64568b7..f32ffcae527e2 100644 --- a/docs/ai/quickstarts/includes/clone-sample-repo.md +++ b/docs/ai/quickstarts/includes/clone-sample-repo.md @@ -5,7 +5,7 @@ ms.date: 07/03/2024 ms.topic: include --- -## Clone the sample repository +## (Optional) Clone the sample repository You can create your own app using the steps in the sections ahead, or you can clone the GitHub repository that contains the completed sample apps for all of the quickstarts. If you plan to use Azure OpenAI, the sample repo is also structured as an Azure Developer CLI template that can provision an Azure OpenAI resource for you. diff --git a/docs/ai/quickstarts/includes/create-ai-service.md b/docs/ai/quickstarts/includes/create-ai-service.md index 2c9532b80d143..c1d7cdcac7a95 100644 --- a/docs/ai/quickstarts/includes/create-ai-service.md +++ b/docs/ai/quickstarts/includes/create-ai-service.md @@ -1,12 +1,8 @@ ## Create the AI service -# [Azure Developer CLI](#tab/azd) - -[!INCLUDE [deploy-azd](deploy-azd.md)] - -# [Azure CLI](#tab/azure-cli) +# [Azure Portal or Azure CLI](#tab/azure-cli) -1. To provision an Azure OpenAI service and model using the Azure CLI, complete the steps in the [Create and deploy an Azure OpenAI Service resource](/azure/ai-services/openai/how-to/create-resource?pivots=cli) article. +1. To provision an Azure OpenAI service and model, complete the steps in the [Create and deploy an Azure OpenAI Service resource](/azure/ai-services/openai/how-to/create-resource) article. 1. From a terminal or command prompt, navigate to the root of your project directory. @@ -18,18 +14,8 @@ dotnet user-secrets set AZURE_OPENAI_GPT_NAME ``` -# [Azure Portal](#tab/azure-portal) - -1. To provision an Azure OpenAI service and model using the Azure portal, complete the steps in the [Create and deploy an Azure OpenAI Service resource](/azure/ai-services/openai/how-to/create-resource?pivots=web-portal) article. - -1. From a terminal or command prompt, navigate to the root of your project directory. - -1. Run the following commands to configure your Azure OpenAI endpoint and model name for the sample app: +# [Azure Developer CLI](#tab/azd) - ```bash - dotnet user-secrets init - dotnet user-secrets set AZURE_OPENAI_ENDPOINT - dotnet user-secrets set AZURE_OPENAI_GPT_NAME - ``` +[!INCLUDE [deploy-azd](deploy-azd.md)] --- diff --git a/docs/ai/quickstarts/prompt-model.md b/docs/ai/quickstarts/prompt-model.md index eebd5b86f054c..91ad6212bab08 100644 --- a/docs/ai/quickstarts/prompt-model.md +++ b/docs/ai/quickstarts/prompt-model.md @@ -1,7 +1,7 @@ --- -title: Quickstart - Summarize text using an AI chat app with .NET +title: Quickstart - Connect to and prompt an AI model with .NET description: Create a simple chat app using Microsoft.Extensions.AI to summarize a text. -ms.date: 04/09/2025 +ms.date: 05/02/2025 ms.topic: quickstart ms.custom: devx-track-dotnet, devx-track-dotnet-ai author: fboucher @@ -10,12 +10,12 @@ zone_pivot_groups: openai-library # CustomerIntent: As a .NET developer new to OpenAI, I want deploy and use sample code to interact to learn from the sample code to summarize text. --- -# Connect to and prompt an AI model using .NET +# Connect to and prompt an AI model In this quickstart, you learn how to create a .NET console chat app to connect to and prompt an OpenAI or Azure OpenAI model. The app uses the library so you can write code using AI abstractions rather than a specific SDK. AI abstractions enable you to change the underlying AI model with minimal code changes. > [!NOTE] -> The [`Microsoft.Extensions.AI`](https://www.nuget.org/packages/Microsoft.Extensions.AI/) library is currently in Preview. +> The library is currently in Preview. :::zone target="docs" pivot="openai" @@ -54,9 +54,9 @@ Complete the following steps to create a .NET console app to connect to an AI mo :::zone target="docs" pivot="azure-openai" ```bash - dotnet add package Azure.Identity dotnet add package Azure.AI.OpenAI - dotnet add package Microsoft.Extensions.AI.OpenAI + dotnet add package Azure.Identity + dotnet add package Microsoft.Extensions.AI.OpenAI --prerelease dotnet add package Microsoft.Extensions.Configuration dotnet add package Microsoft.Extensions.Configuration.UserSecrets ``` @@ -67,18 +67,14 @@ Complete the following steps to create a .NET console app to connect to an AI mo ```bash dotnet add package OpenAI - dotnet add package Microsoft.Extensions.AI.OpenAI + dotnet add package Microsoft.Extensions.AI.OpenAI --prerelease dotnet add package Microsoft.Extensions.Configuration dotnet add package Microsoft.Extensions.Configuration.UserSecrets ``` :::zone-end -1. Open the app in Visual Studio code or your editor of choice - - ```bash - code . - ``` +1. Open the app in Visual Studio Code or your editor of choice. :::zone target="docs" pivot="azure-openai" @@ -94,11 +90,11 @@ Complete the following steps to create a .NET console app to connect to an AI mo 1. Run the following commands to configure your OpenAI API key as a secret for the sample app: - ```bash - dotnet user-secrets init - dotnet user-secrets set OpenAIKey - dotnet user-secrets set ModelName - ``` + ```bash + dotnet user-secrets init + dotnet user-secrets set OpenAIKey + dotnet user-secrets set ModelName + ``` :::zone-end @@ -106,38 +102,40 @@ Complete the following steps to create a .NET console app to connect to an AI mo The app uses the [`Microsoft.Extensions.AI`](https://www.nuget.org/packages/Microsoft.Extensions.AI/) package to send and receive requests to the AI model. -1. In the **Program.cs** file, add the following code to connect and authenticate to the AI model. +1. Copy the [benefits.md](https://raw.githubusercontent.com/dotnet/docs/refs/heads/main/docs/ai/quickstarts/snippets/prompt-completion/azure-openai/benefits.md) file to your project directory. Configure the project to copy this file to the output directory. If you're using Visual Studio, right-click on the file in Solution Explorer, select **Properties**, and then set **Copy to Output Directory** to **Copy if newer**. - :::zone target="docs" pivot="azure-openai" +1. In the `Program.cs` file, add the following code to connect and authenticate to the AI model. - :::code language="csharp" source="snippets/prompt-completion/azure-openai/program.cs" range="1-12"::: + :::zone target="docs" pivot="azure-openai" - > [!NOTE] - > searches for authentication credentials from your local tooling. If you aren't using the `azd` template to provision the Azure OpenAI resource, you'll need to assign the `Azure AI Developer` role to the account you used to sign-in to Visual Studio or the Azure CLI. For more information, see [Authenticate to Azure AI services with .NET](../azure-ai-services-authentication.md). + :::code language="csharp" source="snippets/prompt-completion/azure-openai/program.cs" id="CreateChatClient"::: - :::zone-end + > [!NOTE] + > searches for authentication credentials from your local tooling. If you aren't using the `azd` template to provision the Azure OpenAI resource, you'll need to assign the `Azure AI Developer` role to the account you used to sign-in to Visual Studio or the Azure CLI. For more information, see [Authenticate to Azure AI services with .NET](../azure-ai-services-authentication.md). - :::zone target="docs" pivot="openai" + :::zone-end - :::code language="csharp" source="snippets/prompt-completion/openai/program.cs" range="1-11"::: + :::zone target="docs" pivot="openai" - :::zone-end + :::code language="csharp" source="snippets/prompt-completion/openai/program.cs" id="CreateChatClient"::: -1. Read the *benefits.md* file content and use it to create a prompt for the model. The prompt instructs the model to summarize the file text content. + :::zone-end - :::code language="csharp" source="snippets/prompt-completion/openai/program.cs" range="13-19"::: +1. Add code to read the `benefits.md` file content and then create a prompt for the model. The prompt instructs the model to summarize the file's text content in 20 words or less. -1. Call the `InvokePromptAsync` function to send the prompt to the model to generate a response. + :::code language="csharp" source="snippets/prompt-completion/openai/program.cs" id="CreatePrompt"::: - :::code language="csharp" source="snippets/prompt-completion/openai/program.cs" range="21-23"::: +1. Call the `GetResponseAsync` method to send the prompt to the model to generate a response. -1. Use the `dotnet run` command to run the app: + :::code language="csharp" source="snippets/prompt-completion/openai/program.cs" id="GetResponse"::: - ```dotnetcli - dotnet run - ``` +1. Run the app: + + ```dotnetcli + dotnet run + ``` - The app prints out the completion response from the AI model. Customize the text content of the `benefits.md` file or the length of the summary to see the differences in the responses. + The app prints out the completion response from the AI model. Customize the text content of the `benefits.md` file or the length of the summary to see the differences in the responses. :::zone target="docs" pivot="azure-openai" diff --git a/docs/ai/quickstarts/snippets/image-generation/azure-openai/benefits.md b/docs/ai/quickstarts/snippets/image-generation/azure-openai/benefits.md deleted file mode 100644 index 082b37de0e395..0000000000000 --- a/docs/ai/quickstarts/snippets/image-generation/azure-openai/benefits.md +++ /dev/null @@ -1,22 +0,0 @@ -# Hiking Benefits - -**Hiking** is a wonderful activity that offers a plethora of benefits for both your body and mind. Here are some compelling reasons why you should consider starting hiking: - -1. **Physical Fitness**: - - **Cardiovascular Health**: Hiking gets your heart pumping, improving cardiovascular fitness. The varied terrain challenges your body and burns calories. - - Strength and Endurance: Uphill climbs and uneven trails engage different muscle groups, enhancing strength and endurance. - - Weight Management: Regular hiking can help you maintain a healthy weight. -2. Mental Well-Being: - - Stress Reduction: Nature has a calming effect. Hiking outdoors reduces stress, anxiety, and promotes relaxation. - - Improved Mood: Fresh air, sunlight, and natural surroundings boost your mood and overall happiness. - - Mindfulness: Disconnect from screens and immerse yourself in the present moment. Hiking encourages mindfulness. -3. Connection with Nature: - - Scenic Views: Explore breathtaking landscapes, from lush forests to mountain peaks. Nature's beauty rejuvenates the soul. - - Wildlife Encounters: Spot birds, animals, and plant life. Connecting with nature fosters appreciation and wonder. -4. Social Interaction: - - Group Hikes: Join hiking clubs or go with friends. It's a great way to bond and share experiences. - - Solitude: Solo hikes provide introspection and solitude, allowing you to recharge. -5. Adventure and Exploration: - - Discover Hidden Gems: Hiking takes you off the beaten path. Discover hidden waterfalls, caves, and scenic trails. - - Sense of Accomplishment: Reaching a summit or completing a challenging trail gives a sense of achievement. -Remember, hiking can be tailored to your fitness level—start with shorter, easier trails and gradually progress. Lace up those hiking boots and embark on an adventure! diff --git a/docs/ai/quickstarts/snippets/image-generation/openai/benefits.md b/docs/ai/quickstarts/snippets/image-generation/openai/benefits.md deleted file mode 100644 index 082b37de0e395..0000000000000 --- a/docs/ai/quickstarts/snippets/image-generation/openai/benefits.md +++ /dev/null @@ -1,22 +0,0 @@ -# Hiking Benefits - -**Hiking** is a wonderful activity that offers a plethora of benefits for both your body and mind. Here are some compelling reasons why you should consider starting hiking: - -1. **Physical Fitness**: - - **Cardiovascular Health**: Hiking gets your heart pumping, improving cardiovascular fitness. The varied terrain challenges your body and burns calories. - - Strength and Endurance: Uphill climbs and uneven trails engage different muscle groups, enhancing strength and endurance. - - Weight Management: Regular hiking can help you maintain a healthy weight. -2. Mental Well-Being: - - Stress Reduction: Nature has a calming effect. Hiking outdoors reduces stress, anxiety, and promotes relaxation. - - Improved Mood: Fresh air, sunlight, and natural surroundings boost your mood and overall happiness. - - Mindfulness: Disconnect from screens and immerse yourself in the present moment. Hiking encourages mindfulness. -3. Connection with Nature: - - Scenic Views: Explore breathtaking landscapes, from lush forests to mountain peaks. Nature's beauty rejuvenates the soul. - - Wildlife Encounters: Spot birds, animals, and plant life. Connecting with nature fosters appreciation and wonder. -4. Social Interaction: - - Group Hikes: Join hiking clubs or go with friends. It's a great way to bond and share experiences. - - Solitude: Solo hikes provide introspection and solitude, allowing you to recharge. -5. Adventure and Exploration: - - Discover Hidden Gems: Hiking takes you off the beaten path. Discover hidden waterfalls, caves, and scenic trails. - - Sense of Accomplishment: Reaching a summit or completing a challenging trail gives a sense of achievement. -Remember, hiking can be tailored to your fitness level—start with shorter, easier trails and gradually progress. Lace up those hiking boots and embark on an adventure! diff --git a/docs/ai/quickstarts/snippets/prompt-completion/azure-openai/Program.cs b/docs/ai/quickstarts/snippets/prompt-completion/azure-openai/Program.cs index b4145e6a4d708..b07df36170a0c 100644 --- a/docs/ai/quickstarts/snippets/prompt-completion/azure-openai/Program.cs +++ b/docs/ai/quickstarts/snippets/prompt-completion/azure-openai/Program.cs @@ -1,9 +1,12 @@ -using Microsoft.Extensions.Configuration; +// +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.AI; using Azure.AI.OpenAI; using Azure.Identity; -var config = new ConfigurationBuilder().AddUserSecrets().Build(); +var config = new ConfigurationBuilder() + .AddUserSecrets() + .Build(); string endpoint = config["AZURE_OPENAI_ENDPOINT"]; string deployment = config["AZURE_OPENAI_GPT_NAME"]; @@ -11,15 +14,20 @@ new AzureOpenAIClient(new Uri(endpoint), new DefaultAzureCredential()) .GetChatClient(deployment) .AsIChatClient(); +// -// Create and print out the prompt +// +string text = File.ReadAllText("benefits.md"); string prompt = $""" - summarize the the following text in 20 words or less: - {File.ReadAllText("benefits.md")} + Summarize the the following text in 20 words or less: + {text} """; +// -Console.WriteLine($"user >>> {prompt}"); - -// Submit the prompt and print out the response -ChatResponse response = await client.GetResponseAsync(prompt, new ChatOptions { MaxOutputTokens = 400 }); -Console.WriteLine($"assistant >>> {response}"); +// +// Submit the prompt and print out the response. +ChatResponse response = await client.GetResponseAsync( + prompt, + new ChatOptions { MaxOutputTokens = 400 }); +Console.WriteLine(response); +// diff --git a/docs/ai/quickstarts/snippets/prompt-completion/openai/Program.cs b/docs/ai/quickstarts/snippets/prompt-completion/openai/Program.cs index ae01b4dbf88eb..f8628a6a5b9c7 100644 --- a/docs/ai/quickstarts/snippets/prompt-completion/openai/Program.cs +++ b/docs/ai/quickstarts/snippets/prompt-completion/openai/Program.cs @@ -1,23 +1,30 @@ -using Microsoft.Extensions.AI; +// +using Microsoft.Extensions.AI; using Microsoft.Extensions.Configuration; using OpenAI; -IConfigurationRoot config = new ConfigurationBuilder().AddUserSecrets().Build(); +IConfigurationRoot config = new ConfigurationBuilder() + .AddUserSecrets() + .Build(); string? model = config["ModelName"]; string? key = config["OpenAIKey"]; -// Create the IChatClient IChatClient client = new OpenAIClient(key).GetChatClient(model).AsIChatClient(); +// -// Create and print out the prompt +// +string text = File.ReadAllText("benefits.md"); string prompt = $""" - summarize the the following text in 20 words or less: - {File.ReadAllText("benefits.md")} + Summarize the the following text in 20 words or less: + {text} """; +// -Console.WriteLine($"user >>> {prompt}"); - -// Submit the prompt and print out the response -ChatResponse response = await client.GetResponseAsync(prompt, new ChatOptions { MaxOutputTokens = 400 }); -Console.WriteLine($"assistant >>> {response}"); +// +// Submit the prompt and print out the response. +ChatResponse response = await client.GetResponseAsync( + prompt, + new ChatOptions { MaxOutputTokens = 400 }); +Console.WriteLine(response); +// diff --git a/docs/ai/quickstarts/structured-output.md b/docs/ai/quickstarts/structured-output.md index dc9586121f8c4..117d23e0725f6 100644 --- a/docs/ai/quickstarts/structured-output.md +++ b/docs/ai/quickstarts/structured-output.md @@ -10,6 +10,9 @@ ms.custom: devx-track-dotnet, devx-track-dotnet-ai In this quickstart, you create a chat app that requests a response with *structured output*. A structured output response is a chat response that's of a type you specify instead of just plain text. The chat app you create in this quickstart analyzes sentiment of various product reviews, categorizing each review according to the values of a custom enumeration. +> [!NOTE] +> The library, which is used in this quickstart, is currently in Preview. + ## Prerequisites - [.NET 8 or a later version](https://dotnet.microsoft.com/download) diff --git a/docs/ai/quickstarts/use-function-calling.md b/docs/ai/quickstarts/use-function-calling.md index 6082725a210a0..6f37aa0c7a995 100644 --- a/docs/ai/quickstarts/use-function-calling.md +++ b/docs/ai/quickstarts/use-function-calling.md @@ -75,7 +75,7 @@ Complete the following steps to create a .NET console app to connect to an AI mo :::zone-end -1. Open the app in Visual Studio code or your editor of choice +1. Open the app in Visual Studio Code or your editor of choice ```bash code . diff --git a/docs/ai/toc.yml b/docs/ai/toc.yml index 68229d946e1e0..91f116f0e2d87 100644 --- a/docs/ai/toc.yml +++ b/docs/ai/toc.yml @@ -13,6 +13,8 @@ items: href: microsoft-extensions-ai.md - name: Semantic Kernel href: semantic-kernel-dotnet-overview.md + - name: C# SDK for MCP + href: get-started-mcp.md - name: Quickstarts items: - name: Build a chat app diff --git a/docs/azure/includes/dotnet-all.md b/docs/azure/includes/dotnet-all.md index 9ee6338cbb203..06216a1b26645 100644 --- a/docs/azure/includes/dotnet-all.md +++ b/docs/azure/includes/dotnet-all.md @@ -109,7 +109,7 @@ | Synapse - Monitoring | NuGet [1.0.0-beta.3](https://www.nuget.org/packages/Azure.Analytics.Synapse.Monitoring/1.0.0-beta.3) | [docs](/dotnet/api/overview/azure/Analytics.Synapse.Monitoring-readme?view=azure-dotnet-preview&preserve-view=true) | GitHub [1.0.0-beta.3](https://github.com/Azure/azure-sdk-for-net/tree/Azure.Analytics.Synapse.Monitoring_1.0.0-beta.3/sdk/synapse/Azure.Analytics.Synapse.Monitoring/) | | Synapse - Spark | NuGet [1.0.0-preview.8](https://www.nuget.org/packages/Azure.Analytics.Synapse.Spark/1.0.0-preview.8) | [docs](/dotnet/api/overview/azure/Analytics.Synapse.Spark-readme?view=azure-dotnet-preview&preserve-view=true) | GitHub [1.0.0-preview.8](https://github.com/Azure/azure-sdk-for-net/tree/Azure.Analytics.Synapse.Spark_1.0.0-preview.8/sdk/synapse/Azure.Analytics.Synapse.Spark/) | | System Events | NuGet [1.0.0-beta.2](https://www.nuget.org/packages/Azure.Messaging.EventGrid.SystemEvents/1.0.0-beta.2) | [docs](/dotnet/api/overview/azure/Messaging.EventGrid.SystemEvents-readme?view=azure-dotnet-preview&preserve-view=true) | GitHub [1.0.0-beta.2](https://github.com/Azure/azure-sdk-for-net/tree/Azure.Messaging.EventGrid.SystemEvents_1.0.0-beta.2/sdk/eventgrid/Azure.Messaging.EventGrid.SystemEvents/) | -| System.ClientModel | NuGet [1.3.0](https://www.nuget.org/packages/System.ClientModel/1.3.0)
NuGet [1.4.0-beta.6](https://www.nuget.org/packages/System.ClientModel/1.4.0-beta.6) | [docs](/dotnet/api/overview/azure/System.ClientModel-readme) | GitHub [1.3.0](https://github.com/Azure/azure-sdk-for-net/tree/System.ClientModel_1.3.0/sdk/core/System.ClientModel/)
GitHub [1.4.0-beta.6](https://github.com/Azure/azure-sdk-for-net/tree/System.ClientModel_1.4.0-beta.6/sdk/core/System.ClientModel/) | +| System.ClientModel | NuGet [1.4.0](https://www.nuget.org/packages/System.ClientModel/1.4.0) | [docs](/dotnet/api/overview/azure/System.ClientModel-readme) | GitHub [1.4.0](https://github.com/Azure/azure-sdk-for-net/tree/System.ClientModel_1.4.0/sdk/core/System.ClientModel/) | | Tables | NuGet [12.10.0](https://www.nuget.org/packages/Azure.Data.Tables/12.10.0) | [docs](/dotnet/api/overview/azure/Data.Tables-readme) | GitHub [12.10.0](https://github.com/Azure/azure-sdk-for-net/tree/Azure.Data.Tables_12.10.0/sdk/tables/Azure.Data.Tables/) | | Text Analytics | NuGet [5.3.0](https://www.nuget.org/packages/Azure.AI.TextAnalytics/5.3.0) | [docs](/dotnet/api/overview/azure/AI.TextAnalytics-readme) | GitHub [5.3.0](https://github.com/Azure/azure-sdk-for-net/tree/Azure.AI.TextAnalytics_5.3.0/sdk/textanalytics/Azure.AI.TextAnalytics/) | | Text Authoring | NuGet [1.0.0-beta.1](https://www.nuget.org/packages/Azure.AI.Language.Text.Authoring/1.0.0-beta.1) | [docs](/dotnet/api/overview/azure/AI.Language.Text.Authoring-readme?view=azure-dotnet-preview&preserve-view=true) | GitHub [1.0.0-beta.1](https://github.com/Azure/azure-sdk-for-net/tree/Azure.AI.Language.Text.Authoring_1.0.0-beta.1/sdk/cognitivelanguage/Azure.AI.Language.Text.Authoring/) | diff --git a/docs/azure/includes/dotnet-new.md b/docs/azure/includes/dotnet-new.md index e646c3430c507..93a9c366f7e2f 100644 --- a/docs/azure/includes/dotnet-new.md +++ b/docs/azure/includes/dotnet-new.md @@ -113,7 +113,7 @@ | Synapse - Monitoring | NuGet [1.0.0-beta.3](https://www.nuget.org/packages/Azure.Analytics.Synapse.Monitoring/1.0.0-beta.3) | [docs](/dotnet/api/overview/azure/Analytics.Synapse.Monitoring-readme?view=azure-dotnet-preview&preserve-view=true) | GitHub [1.0.0-beta.3](https://github.com/Azure/azure-sdk-for-net/tree/Azure.Analytics.Synapse.Monitoring_1.0.0-beta.3/sdk/synapse/Azure.Analytics.Synapse.Monitoring/) | | Synapse - Spark | NuGet [1.0.0-preview.8](https://www.nuget.org/packages/Azure.Analytics.Synapse.Spark/1.0.0-preview.8) | [docs](/dotnet/api/overview/azure/Analytics.Synapse.Spark-readme?view=azure-dotnet-preview&preserve-view=true) | GitHub [1.0.0-preview.8](https://github.com/Azure/azure-sdk-for-net/tree/Azure.Analytics.Synapse.Spark_1.0.0-preview.8/sdk/synapse/Azure.Analytics.Synapse.Spark/) | | System Events | NuGet [1.0.0-beta.2](https://www.nuget.org/packages/Azure.Messaging.EventGrid.SystemEvents/1.0.0-beta.2) | [docs](/dotnet/api/overview/azure/Messaging.EventGrid.SystemEvents-readme?view=azure-dotnet-preview&preserve-view=true) | GitHub [1.0.0-beta.2](https://github.com/Azure/azure-sdk-for-net/tree/Azure.Messaging.EventGrid.SystemEvents_1.0.0-beta.2/sdk/eventgrid/Azure.Messaging.EventGrid.SystemEvents/) | -| System.ClientModel | NuGet [1.3.0](https://www.nuget.org/packages/System.ClientModel/1.3.0)
NuGet [1.4.0-beta.6](https://www.nuget.org/packages/System.ClientModel/1.4.0-beta.6) | [docs](/dotnet/api/overview/azure/System.ClientModel-readme) | GitHub [1.3.0](https://github.com/Azure/azure-sdk-for-net/tree/System.ClientModel_1.3.0/sdk/core/System.ClientModel/)
GitHub [1.4.0-beta.6](https://github.com/Azure/azure-sdk-for-net/tree/System.ClientModel_1.4.0-beta.6/sdk/core/System.ClientModel/) | +| System.ClientModel | NuGet [1.4.0](https://www.nuget.org/packages/System.ClientModel/1.4.0) | [docs](/dotnet/api/overview/azure/System.ClientModel-readme) | GitHub [1.4.0](https://github.com/Azure/azure-sdk-for-net/tree/System.ClientModel_1.4.0/sdk/core/System.ClientModel/) | | Tables | NuGet [12.10.0](https://www.nuget.org/packages/Azure.Data.Tables/12.10.0) | [docs](/dotnet/api/overview/azure/Data.Tables-readme) | GitHub [12.10.0](https://github.com/Azure/azure-sdk-for-net/tree/Azure.Data.Tables_12.10.0/sdk/tables/Azure.Data.Tables/) | | Text Analytics | NuGet [5.3.0](https://www.nuget.org/packages/Azure.AI.TextAnalytics/5.3.0) | [docs](/dotnet/api/overview/azure/AI.TextAnalytics-readme) | GitHub [5.3.0](https://github.com/Azure/azure-sdk-for-net/tree/Azure.AI.TextAnalytics_5.3.0/sdk/textanalytics/Azure.AI.TextAnalytics/) | | Text Authoring | NuGet [1.0.0-beta.1](https://www.nuget.org/packages/Azure.AI.Language.Text.Authoring/1.0.0-beta.1) | [docs](/dotnet/api/overview/azure/AI.Language.Text.Authoring-readme?view=azure-dotnet-preview&preserve-view=true) | GitHub [1.0.0-beta.1](https://github.com/Azure/azure-sdk-for-net/tree/Azure.AI.Language.Text.Authoring_1.0.0-beta.1/sdk/cognitivelanguage/Azure.AI.Language.Text.Authoring/) | diff --git a/docs/azure/index.yml b/docs/azure/index.yml index fbb9e38f2aedb..c0a20915db639 100644 --- a/docs/azure/index.yml +++ b/docs/azure/index.yml @@ -99,11 +99,11 @@ conceptualContent: url: ../ai/overview.md text: AI for .NET overview - itemType: quickstart - url: ../ai/quickstarts/get-started-openai.md + url: ../ai/quickstarts/build-chat-app.md text: Build a chat app - itemType: quickstart text: Generate images - url: ../ai/quickstarts/quickstart-openai-generate-images.md + url: ../ai/quickstarts/generate-images.md - itemType: concept text: Understand prompt engineering url: ../ai/conceptual/prompt-engineering-dotnet.md diff --git a/docs/azure/sdk/configure-proxy.md b/docs/azure/sdk/configure-proxy.md index b9ef373719038..2ca9b0280c69c 100644 --- a/docs/azure/sdk/configure-proxy.md +++ b/docs/azure/sdk/configure-proxy.md @@ -41,7 +41,7 @@ The following table provides an inventory of environment variables that can be s For a deep understanding of how these environment variables are processed, see [the code](https://github.com/Azure/azure-sdk-for-net/blob/9aa3b3a44f81bc0be5a4fc86607e0150ba9815d5/sdk/core/Azure.Core/src/Pipeline/Internal/HttpEnvironmentProxy.cs#L31). Be aware of the following behaviors: -- Each environment variable in the preceding table, except `GATEWAY_INTERFACE`, can alternatively be defined as lowercase. The lowercase form takes precedence over the uppercase form.` +- Each environment variable in the preceding table, except `GATEWAY_INTERFACE`, can alternatively be defined as lowercase. The lowercase form takes precedence over the uppercase form. - If both `http_proxy` and `GATEWAY_INTERFACE` are undefined, `HTTP_PROXY` is used. - `ALL_PROXY` is considered only when either an HTTP or an HTTPS proxy is undefined. - Protocol-specific environment variables take precedence over `ALL_PROXY`. diff --git a/docs/core/deploying/native-aot/index.md b/docs/core/deploying/native-aot/index.md index e134a633eacfc..4cb03365c8d27 100644 --- a/docs/core/deploying/native-aot/index.md +++ b/docs/core/deploying/native-aot/index.md @@ -134,6 +134,7 @@ Native AOT apps have the following limitations: - Implies compilation into a single file, which has known [incompatibilities](../single-file/overview.md#api-incompatibility). - Apps include required runtime libraries (just like [self-contained apps](../index.md#publish-self-contained), increasing their size as compared to framework-dependent apps). - always use their interpreted form, which is slower than run-time generated compiled code. +- Generic parameters substituted with struct type arguments will have specialized code generated for each instantiation. In the dynamic runtime, many instantiations are generated on-demand. In Native AOT, all instantiations are pre-generated. This can have significant impact to the disk size of the application. Generic virtual methods and generic instance methods will also have an instantiation for every implementing or overriding type. - Not all the runtime libraries are fully annotated to be Native AOT compatible. That is, some warnings in the runtime libraries aren't actionable by end developers. - [Diagnostic support for debugging and profiling](./diagnostics.md) with some limitations. - Support for some ASP.NET Core features. For more information, see [ASP.NET Core support for Native AOT](/aspnet/core/fundamentals/native-aot/). diff --git a/docs/csharp/fundamentals/object-oriented/index.md b/docs/csharp/fundamentals/object-oriented/index.md index 976b99ff5b4de..a4069b1da5a58 100644 --- a/docs/csharp/fundamentals/object-oriented/index.md +++ b/docs/csharp/fundamentals/object-oriented/index.md @@ -18,7 +18,7 @@ In C#, the definition of a type—a class, struct, or record—is like a ## Encapsulation - *Encapsulation* is sometimes referred to as the first pillar or principle of object-oriented programming. A class or struct can specify how accessible each of its members is to code outside of the class or struct. Member not intended for consumers outside of the class or assembly are hidden to limit the potential for coding errors or malicious exploits. For more information, see the [Object-oriented programming](../tutorials/oop.md) tutorial. + *Encapsulation* is sometimes referred to as the first pillar or principle of object-oriented programming. A class or struct can specify how accessible each of its members is to code outside of the class or struct. Members not intended for consumers outside of the class or assembly are hidden to limit the potential for coding errors or malicious exploits. For more information, see the [Object-oriented programming](../tutorials/oop.md) tutorial. ## Members diff --git a/docs/csharp/language-reference/tokens/interpolated.md b/docs/csharp/language-reference/tokens/interpolated.md index fab7606294997..8ea3d4c109bc1 100644 --- a/docs/csharp/language-reference/tokens/interpolated.md +++ b/docs/csharp/language-reference/tokens/interpolated.md @@ -88,7 +88,7 @@ For more information about custom formatting, see the [Custom formatting with IC ## Other resources -If you're new to string interpolation, see the [String interpolation in C#](../../tutorials/exploration/interpolated-strings.yml) interactive tutorial. You can also check another [String interpolation in C#](../../tutorials/string-interpolation.md) tutorial. That tutorial demonstrates how to use interpolated strings to produce formatted strings. +If you're new to string interpolation, see the [String interpolation in C#](../../tutorials/string-interpolation.md) interactive tutorial. That tutorial demonstrates how to use interpolated strings to produce formatted strings. ## Compilation of interpolated strings diff --git a/docs/csharp/misc/cs0449.md b/docs/csharp/misc/cs0449.md index 911dd934608da..2a9902e33c071 100644 --- a/docs/csharp/misc/cs0449.md +++ b/docs/csharp/misc/cs0449.md @@ -10,24 +10,25 @@ ms.assetid: 32c07a2c-4c48-4d07-b643-72422a6b9fac --- # Compiler Error CS0449 -The 'class' or 'struct' constraint must come before any other constraints - - The constraints on the type parameter of a generic type or method must occur in a specific order: `class` or `struct` must be first, if present, then any interface constraints, and finally any constructor constraints. This error is caused by the `class` or `struct` constraint not appearing first. To resolve this error, reorder the constraint clauses. - +The `'class'`, `'struct'`, `'unmanaged'`, `'notnull'`, and `'default'` constraints cannot be combined or duplicated, and must be specified first in the constraints list. + +The constraints on the type parameter of a generic type or method must occur in a specific order: `class` or `struct` must be first, if present, then any interface constraints, and finally any constructor constraints. This error is caused by the `class` or `struct` constraint not appearing first. To resolve this error, reorder the constraint clauses. + ## Example The following sample generates CS0449. - + ```csharp // CS0449.cs // compile with: /target:library -interface I {} +public interface I {} // Made public to avoid CS0703 + public class C4 { public void F1() where T : class, struct, I {} // CS0449 public void F2() where T : I, struct {} // CS0449 public void F3() where T : I, class {} // CS0449 - + // OK public void F4() where T : class {} public void F5() where T : struct {} diff --git a/docs/csharp/programming-guide/strings/index.md b/docs/csharp/programming-guide/strings/index.md index 35f77255e8721..26bd10874d165 100644 --- a/docs/csharp/programming-guide/strings/index.md +++ b/docs/csharp/programming-guide/strings/index.md @@ -106,7 +106,7 @@ A format string is a string whose contents are determined dynamically at run tim ### String interpolation -You declare [*Interpolated strings*](../../language-reference/tokens/interpolated.md) with the `$` special character. An interpolated string includes interpolated expressions in braces. If you're new to string interpolation, see the [String interpolation - C# interactive tutorial](../../tutorials/exploration/interpolated-strings.yml) for a quick overview. +You declare [*Interpolated strings*](../../language-reference/tokens/interpolated.md) with the `$` special character. An interpolated string includes interpolated expressions in braces. If you're new to string interpolation, see the [String interpolation - C# tutorial](../../tutorials/string-interpolation.md) for several examples. Use string interpolation to improve the readability and maintainability of your code. String interpolation achieves the same results as the `String.Format` method, but is easier to use and improves inline clarity. diff --git a/docs/csharp/toc.yml b/docs/csharp/toc.yml index 735ed842fbc44..7a89acd91ef69 100644 --- a/docs/csharp/toc.yml +++ b/docs/csharp/toc.yml @@ -186,13 +186,9 @@ items: href: tutorials/ranges-indexes.md - name: Work with nullable reference types href: tutorials/nullable-reference-types.md - - name: Explore string interpolation - interactive - href: tutorials/exploration/interpolated-strings.yml - - name: Explore string interpolation - in your environment - href: tutorials/exploration/interpolated-strings-local.md - name: Explore patterns in objects href: tutorials/patterns-objects.md - - name: Advanced scenarios for string Interpolation + - name: String interpolation href: tutorials/string-interpolation.md - name: Console Application href: tutorials/console-teleprompter.md diff --git a/docs/csharp/tutorials/exploration/interpolated-strings-local.md b/docs/csharp/tutorials/exploration/interpolated-strings-local.md deleted file mode 100644 index 1aae9581ea3bf..0000000000000 --- a/docs/csharp/tutorials/exploration/interpolated-strings-local.md +++ /dev/null @@ -1,162 +0,0 @@ ---- -title: String interpolation tutorial -description: This tutorial shows you how to use the C# string interpolation feature to include formatted expression results in a larger string. -ms.date: 10/23/2018 ---- -# Use string interpolation to construct formatted strings - -This tutorial teaches you how to use C# [string interpolation](../../language-reference/tokens/interpolated.md) to insert values into a single result string. You write C# code and see the results of compiling and running it. The tutorial contains a series of lessons that show you how to insert values into a string and format those values in different ways. - -This tutorial expects that you have a machine you can use for development. The .NET tutorial [Hello World in 10 minutes](https://dotnet.microsoft.com/learn/dotnet/hello-world-tutorial/intro) has instructions for setting up your local development environment on Windows, Linux, or macOS. You can also complete the [interactive version](interpolated-strings.yml) of this tutorial in your browser. - -## Create an interpolated string - -Create a directory named *interpolated*. Make it the current directory and run the following command from a console window: - -```dotnetcli -dotnet new console -``` - -This command creates a new .NET Core console application in the current directory. - -Open *Program.cs* in your favorite editor, and replace the line `Console.WriteLine("Hello World!");` with the following code, where you replace `` with your name: - -```csharp -var name = ""; -Console.WriteLine($"Hello, {name}. It's a pleasure to meet you!"); -``` - -Try this code by typing `dotnet run` in your console window. When you run the program, it displays a single string that includes your name in the greeting. The string included in the method call is an *interpolated string expression*. It's a kind of template that lets you construct a single string (called the *result string*) from a string that includes embedded code. Interpolated strings are particularly useful for inserting values into a string or concatenating (joining together) strings. - -This simple example contains the two elements that every interpolated string must have: - -- A string literal that begins with the `$` character before its opening quotation mark character. There can't be any spaces between the `$` symbol and the quotation mark character. (If you'd like to see what happens if you include one, insert a space after the `$` character, save the file, and run the program again by typing `dotnet run` in the console window. The C# compiler displays an error message, "error CS1056: Unexpected character '$'".) - -- One or more *interpolation expressions*. An interpolation expression is indicated by an opening and closing brace (`{` and `}`). You can put any C# expression that returns a value (including `null`) inside the braces. - -Let's try a few more string interpolation examples with some other data types. - -## Include different data types - -In the previous section, you used string interpolation to insert one string inside of another. The result of an interpolation expression can be of any data type, though. Let's include values of various data types in an interpolated string. - -In the following example, we first define a [class](../../fundamentals/types/classes.md) data type `Vegetable` that has a `Name` [property](../../programming-guide/classes-and-structs/properties.md) and a `ToString` [method](../../methods.md), which [overrides](../../language-reference/keywords/override.md) the behavior of the method. The [`public` access modifier](../../language-reference/keywords/public.md) makes that method available to any client code to get the string representation of a `Vegetable` instance. In the example the `Vegetable.ToString` method returns the value of the `Name` property that is initialized at the `Vegetable` [constructor](../../programming-guide/classes-and-structs/constructors.md): - -```csharp -public Vegetable(string name) => Name = name; -``` - -Then we create an instance of the `Vegetable` class named `item` by using the [`new` operator](../../language-reference/operators/new-operator.md) and providing a name for the constructor `Vegetable`: - -```csharp -var item = new Vegetable("eggplant"); -``` - -Finally, we include the `item` variable into an interpolated string that also contains a value, a value, and a `Unit` [enumeration](../../language-reference/builtin-types/enum.md) value. Replace all of the C# code in your editor with the following code, and then use the `dotnet run` command to run it: - -```csharp -using System; - -public class Vegetable -{ - public Vegetable(string name) => Name = name; - - public string Name { get; } - - public override string ToString() => Name; -} - -public class Program -{ - public enum Unit { item, kilogram, gram, dozen }; - - public static void Main() - { - var item = new Vegetable("eggplant"); - var date = DateTime.Now; - var price = 1.99m; - var unit = Unit.item; - Console.WriteLine($"On {date}, the price of {item} was {price} per {unit}."); - } -} -``` - -Note that the interpolation expression `item` in the interpolated string resolves to the text "eggplant" in the result string. That's because, when the type of the expression result is not a string, the result is resolved to a string in the following way: - -- If the interpolation expression evaluates to `null`, an empty string ("", or ) is used. - -- If the interpolation expression doesn't evaluate to `null`, typically the `ToString` method of the result type is called. You can test this by updating the implementation of the `Vegetable.ToString` method. You might not even need to implement the `ToString` method since every type has some implementation of this method. To test this, comment out the definition of the `Vegetable.ToString` method in the example (to do that, put a comment symbol, `//`, in front of it). In the output, the string "eggplant" is replaced by the fully qualified type name ("Vegetable" in this example), which is the default behavior of the method. The default behavior of the `ToString` method for an enumeration value is to return the string representation of the value. - -In the output from this example, the date is too precise (the price of eggplant doesn't change every second), and the price value doesn't indicate a unit of currency. In the next section, you'll learn how to fix those issues by controlling the format of string representations of the expression results. - -## Control the formatting of interpolation expressions - -In the previous section, two poorly formatted strings were inserted into the result string. One was a date and time value for which only the date was appropriate. The second was a price that didn't indicate its unit of currency. Both issues are easy to address. String interpolation lets you specify *format strings* that control the formatting of particular types. Modify the call to `Console.WriteLine` from the previous example to include the format strings for the date and price expressions as shown in the following line: - -```csharp -Console.WriteLine($"On {date:d}, the price of {item} was {price:C2} per {unit}."); -``` - -You specify a format string by following the interpolation expression with a colon (":") and the format string. "d" is a [standard date and time format string](../../../standard/base-types/standard-date-and-time-format-strings.md#the-short-date-d-format-specifier) that represents the short date format. "C2" is a [standard numeric format string](../../../standard/base-types/standard-numeric-format-strings.md#currency-format-specifier-c) that represents a number as a currency value with two digits after the decimal point. - -A number of types in the .NET libraries support a predefined set of format strings. These include all the numeric types and the date and time types. For a complete list of types that support format strings, see [Format Strings and .NET Class Library Types](../../../standard/base-types/formatting-types.md#format-strings-and-net-types) in the [Formatting Types in .NET](../../../standard/base-types/formatting-types.md) article. - -Try modifying the format strings in your text editor and, each time you make a change, rerun the program to see how the changes affect the formatting of the date and time and the numeric value. Change the "d" in `{date:d}` to "t" (to display the short time format), "y" (to display the year and month), and "yyyy" (to display the year as a four-digit number). Change the "C2" in `{price:C2}` to "e" (for exponential notation) and "F3" (for a numeric value with three digits after the decimal point). - -In addition to controlling formatting, you can also control the field width and alignment of the formatted strings that are included in the result string. In the next section, you'll learn how to do this. - -## Control the field width and alignment of interpolation expressions - -Ordinarily, when the result of an interpolation expression is formatted to string, that string is included in a result string without leading or trailing spaces. Particularly when you work with a set of data, being able to control a field width and text alignment helps to produce a more readable output. To see this, replace all the code in your text editor with the following code, then type `dotnet run` to execute the program: - -```csharp -using System; -using System.Collections.Generic; - -public class Example -{ - public static void Main() - { - var titles = new Dictionary() - { - ["Doyle, Arthur Conan"] = "Hound of the Baskervilles, The", - ["London, Jack"] = "Call of the Wild, The", - ["Shakespeare, William"] = "Tempest, The" - }; - - Console.WriteLine("Author and Title List"); - Console.WriteLine(); - Console.WriteLine($"|{"Author",-25}|{"Title",30}|"); - foreach (var title in titles) - Console.WriteLine($"|{title.Key,-25}|{title.Value,30}|"); - } -} -``` - -The names of authors are left-aligned, and the titles they wrote are right-aligned. You specify the alignment by adding a comma (",") after an interpolation expression and designating the *minimum* field width. If the specified value is a positive number, the field is right-aligned. If it is a negative number, the field is left-aligned. - -Try removing the negative signs from the `{"Author",-25}` and `{title.Key,-25}` code and run the example again, as the following code does: - -```csharp -Console.WriteLine($"|{"Author",25}|{"Title",30}|"); -foreach (var title in titles) - Console.WriteLine($"|{title.Key,25}|{title.Value,30}|"); -``` - -This time, the author information is right-aligned. - -You can combine an alignment specifier and a format string for a single interpolation expression. To do that, specify the alignment first, followed by a colon and the format string. Replace all of the code inside the `Main` method with the following code, which displays three formatted strings with defined field widths. Then run the program by entering the `dotnet run` command. - -```csharp -Console.WriteLine($"[{DateTime.Now,-20:d}] Hour [{DateTime.Now,-10:HH}] [{1063.342,15:N2}] feet"); -``` - -The output looks something like the following: - -```console -[04/14/2018 ] Hour [16 ] [ 1,063.34] feet -``` - -You've completed the string interpolation tutorial. - -For more information, see the [String interpolation](../../language-reference/tokens/interpolated.md) topic and the [String interpolation in C#](../string-interpolation.md) tutorial. diff --git a/docs/csharp/tutorials/exploration/interpolated-strings.yml b/docs/csharp/tutorials/exploration/interpolated-strings.yml deleted file mode 100644 index 20f86dfece642..0000000000000 --- a/docs/csharp/tutorials/exploration/interpolated-strings.yml +++ /dev/null @@ -1,108 +0,0 @@ -### YamlMime:Tutorial -title: Use string interpolation to construct formatted strings -metadata: - title: String interpolation interactive tutorial - description: In this tutorial, you use your browser to explore the C# string interpolation feature interactively. You write C# code and see the results of compiling and running your code directly in the browser. - audience: Developer - ms.custom: mvc - ms.date: 08/24/2018 - ms.topic: interactive-tutorial - level: Beginner - displayType: two-column - interactive: csharp -items: -- durationInMinutes: 2 - content: | - This tutorial teaches you how to use [string interpolation](../../language-reference/tokens/interpolated.md) to insert values into a single string. You also learn how to control text formatting of the result string. You use your browser to write and run C# code and can immediately see the results. -- title: Create an interpolated string - durationInMinutes: 2 - content: | - Run the following code in the interactive window. Select the **Enter focus mode** button. Then, type the following code block in the interactive window (replace `` with your name) and select **Run**: - - ```csharp - var name = ""; - Console.WriteLine($"Hello, {name}. It's a pleasure to meet you!"); - ``` - - When you run the code, **Output** displays a string that includes your name in the greeting. The string argument of the method call is an *interpolated string expression*. It's a kind of template that lets you construct a single string (called the *result string*) from a string that includes embedded code. Interpolated string expressions are particularly useful for inserting values into a string or concatenating (joining together) several strings. - - The example above contains the two elements that every interpolated string expression must have: - - - A string literal that begins with the `$` character before its opening quotation mark character. There can't be any spaces between the `$` symbol and the quotation mark character. (If you'd like to see what happens if you include one, insert a space after the `$` character in the interactive window and run the updated code. The C# compiler complains, "Unexpected character '$'".) - - - One or more *interpolation expressions*. An interpolation expression is indicated by an opening and closing brace (`{` and `}`). You can put any C# expression that returns a value (including `null`) inside the braces. - - Let's try a few more string interpolation examples with some other data types. - -- title: Include different data types - durationInMinutes: 5 - content: | - In the previous step, you used string interpolation to insert one string inside of another. Each interpolation expression that is part of an interpolated string expression can be of any data type, though. Let's include values of various data type expressions in an interpolated string. - - In the following example, we first define a [tuple](../../language-reference/builtin-types/value-tuples.md) that has `Name`, `Price`, and `perPackage` members. Run the following code in the interactive window: - - ```csharp - var item = (Name: "eggplant", Price: 1.99m, perPackage: 3); - var date = DateTime.Now; - Console.WriteLine($"On {date}, the price of {item.Name} was {item.Price} per {item.perPackage} items."); - ``` - - Note that the interpolation expression `item.Price` in the interpolated string resolves to the text "1.99" in the result string. That's because, when the type of the expression result is not a string, the result is resolved to a string in the following way: - - - If the interpolation expression evaluates to `null`, an empty string ("", or ) is used. - - - If the interpolation expression doesn't evaluate to `null`, typically the `ToString` method of the result expression is called. - - In the output from this example, the date is too precise (the price of eggplant doesn't change every second), and the price value doesn't indicate a unit of currency. In the next step, you'll learn how to fix those issues by controlling the format of string representations of the expression results. - -- title: Control the formatting of interpolation expressions - durationInMinutes: 5 - content: | - In the previous step, two poorly formatted strings were inserted into the result string. One was a date and time value for which only the date was appropriate. The second was a price that didn't indicate its unit of currency. Both issues are easy to address. String interpolation lets you specify *format strings* that control the formatting of particular types. Modify the call to `Console.WriteLine` from the previous example to include the format strings for the date and price expressions as shown in the following line: - - ```csharp - Console.WriteLine($"On {date:d}, the price of {item.Name} was {item.Price:C2} per {item.perPackage} items"); - ``` - - You specify a format string by following the interpolation expression with a colon (":") and the format string. "d" is a [standard date and time format string](../../../standard/base-types/standard-date-and-time-format-strings.md#the-short-date-d-format-specifier) that represents the short date format. "C2" is a [standard numeric format string](../../../standard/base-types/standard-numeric-format-strings.md#currency-format-specifier-c) that represents a number as a currency value with two digits after the decimal point. - - A number of types in the .NET libraries support a predefined set of format strings. These include all the numeric types and the date and time types. For a complete list of types that support format strings, see [Format Strings and .NET Class Library Types](../../../standard/base-types/formatting-types.md#format-strings-and-net-types) in the [Formatting Types in .NET](../../../standard/base-types/formatting-types.md) article. - - Try modifying the format strings in the example to see how they affect the formatting of the date and time and the numeric value. Change the "d" in `{date:d}` to "t" (to display the short time format), "y" (to display the year and month), and "yyyy" (to display the year as a four-digit number). Change the "C2" in `{price:C2}` to "e" (for exponential notation) and "F3" (for a numeric value with three digits after the decimal point). - - In addition to controlling formatting, you can also control the field width and alignment of the formatted strings that are included in the result string. In the next step, you'll learn how to do this. - -- title: Control the field width and alignment of interpolation expressions - durationInMinutes: 6 - content: | - Ordinarily, when the result of an interpolated string expression is formatted to string, that string is included in a result string without leading or trailing spaces. Particularly when you work with a set of data, being able to control a field width and text alignment helps to produce a more readable output. To see this, run the following code: - - ```csharp - var inventory = new Dictionary() - { - ["hammer, ball pein"] = 18, - ["hammer, cross pein"] = 5, - ["screwdriver, Phillips #2"] = 14 - }; - - Console.WriteLine($"Inventory on {DateTime.Now:d}"); - Console.WriteLine(" "); - Console.WriteLine($"|{"Item",-25}|{"Quantity",10}|"); - foreach (var item in inventory) - Console.WriteLine($"|{item.Key,-25}|{item.Value,10}|"); - ``` - - The item names are left-aligned, and their quantities are right-aligned. You specify the alignment by adding a comma (",") after an interpolation expression and designating the *minimum* field width. If the specified value is a positive number, the field is right-aligned. If it is a negative number, the field is left-aligned. - - Try removing the negative signs from the `{"Item",-25}` and `{item.Key,-25}` code and run the example again. This time, the item names are right-aligned. - - You can combine an alignment specifier and a format string for a single interpolation expression. To do that, specify the alignment first, followed by a colon and the format string. Try the following code that displays three formatted strings with defined field widths: - - ```csharp - Console.WriteLine($"[{DateTime.Now,-20:d}] Hour [{DateTime.Now,-10:HH}] [{1063.342,15:N2}] feet"); - ``` - -- content: | - You've completed the string interpolation interactive tutorial. You can visit the [.NET site](https://dotnet.microsoft.com/learn/dotnet/hello-world-tutorial/intro) to download the .NET Core SDK, create a project on your machine, and keep coding. - - For more information, see [String interpolation](../../language-reference/tokens/interpolated.md). diff --git a/docs/csharp/tutorials/snippets/StringInterpolation/Program.cs b/docs/csharp/tutorials/snippets/StringInterpolation/Program.cs index 7f1183e7d957d..8a270a1365ac6 100644 --- a/docs/csharp/tutorials/snippets/StringInterpolation/Program.cs +++ b/docs/csharp/tutorials/snippets/StringInterpolation/Program.cs @@ -50,6 +50,34 @@ private static void SpecifyFormatString() // } + private static void SpecifyAlignment() + { + + // + var titles = new Dictionary() + { + ["Doyle, Arthur Conan"] = "Hound of the Baskervilles, The", + ["London, Jack"] = "Call of the Wild, The", + ["Shakespeare, William"] = "Tempest, The" + }; + + Console.WriteLine("Author and Title List"); + Console.WriteLine(); + Console.WriteLine($"|{"Author",-25}|{"Title",30}|"); + foreach (var title in titles) + { + Console.WriteLine($"|{title.Key,-25}|{title.Value,30}|"); + } + // Output: + // Author and Title List + // + // |Author |Title | + // |Doyle, Arthur Conan |Hound of the Baskervilles, The | + // |London, Jack | Call of the Wild, The | + // |Shakespeare, William | Tempest, The | + // + } + private static void SpecifyAlignmentAndFormat() { // diff --git a/docs/csharp/tutorials/string-interpolation.md b/docs/csharp/tutorials/string-interpolation.md index 5bf22fd22279f..65e2624751a24 100644 --- a/docs/csharp/tutorials/string-interpolation.md +++ b/docs/csharp/tutorials/string-interpolation.md @@ -3,11 +3,11 @@ title: String interpolation description: Learn how to include formatted expression results in a result string in C# with string interpolation. author: pkulikov ms.subservice: fundamentals -ms.date: 08/28/2023 +ms.date: 05/05/2025 --- # String interpolation in C\# -This tutorial shows you how to use [string interpolation](../language-reference/tokens/interpolated.md) to format and include expression results in a result string. The examples assume that you are familiar with basic C# concepts and .NET type formatting. If you are new to string interpolation or .NET type formatting, check out the [interactive string interpolation tutorial](exploration/interpolated-strings.yml) first. For more information about formatting types in .NET, see [Formatting types in .NET](../../standard/base-types/formatting-types.md). +This tutorial shows you how to use [string interpolation](../language-reference/tokens/interpolated.md) to format and include expression results in a result string. The examples assume that you're familiar with basic C# concepts and .NET type formatting. For more information about formatting types in .NET, see [Formatting types in .NET](../../standard/base-types/formatting-types.md). ## Introduction @@ -21,11 +21,19 @@ As the example shows, you include an expression in an interpolated string by enc {} ``` -Interpolated strings support all the capabilities of the [string composite formatting](../../standard/base-types/composite-formatting.md) feature. That makes them a more readable alternative to the use of the method. +Interpolated strings support all the capabilities of the [string composite formatting](../../standard/base-types/composite-formatting.md) feature. That makes them a more readable alternative to the use of the method. Every interpolated string must have: + +- A string literal that begins with the `$` character before its opening quotation mark character. There can't be any spaces between the `$` symbol and the quotation mark character. +- One or more *interpolation expressions*. You indicate an interpolation expression with an opening and closing brace (`{` and `}`). You can put any C# expression that returns a value (including `null`) inside the braces. + +C# evaluates the expression between the `{` and `}` characters with the following rules: + +- If the interpolation expression evaluates to `null`, an empty string ("", or ) is used. +- If the interpolation expression doesn't evaluate to `null`, typically the `ToString` method of the result type is called. ## How to specify a format string for an interpolation expression -To specify a format string that's supported by the type of the expression result, follow the interpolation expression with a colon (":") and the format string: +To specify a format string supported by the type of the expression result, follow the interpolation expression with a colon (":") and the format string: ```csharp {:} @@ -45,7 +53,11 @@ To specify the minimum field width and the alignment of the formatted expression {,} ``` -If the *width* value is positive, the formatted expression result is right-aligned; if negative, it's left-aligned. +The following code sample uses the minimum field width to create a tabular output: + +:::code language="csharp" interactive="try-dotnet-method" source="./snippets/StringInterpolation/Program.cs" id="AlignmentString"::: + +If the *width* value is positive, the formatted expression result is right-aligned; if negative, it's left-aligned. Remove the `-` signs before the width specifier and run the sample again to see the results. If you need to specify both width and a format string, start with the width component: @@ -65,7 +77,7 @@ For more information, see the [Width component](../../standard/base-types/compos Interpolated strings support all escape sequences that can be used in ordinary string literals. For more information, see [String escape sequences](../programming-guide/strings/index.md#string-escape-sequences). -To interpret escape sequences literally, use a [verbatim](../language-reference/tokens/verbatim.md) string literal. An interpolated verbatim string starts with the both `$` and `@` characters. You can use `$` and `@` in any order: both `$@"..."` and `@$"..."` are valid interpolated verbatim strings. +To interpret escape sequences literally, use a [verbatim](../language-reference/tokens/verbatim.md) string literal. An interpolated verbatim string starts with both the `$` and `@` characters. You can use `$` and `@` in any order: both `$@"..."` and `@$"..."` are valid interpolated verbatim strings. To include a brace, "{" or "}", in a result string, use two braces, "{{" or "}}". For more information, see the [Escaping braces](../../standard/base-types/composite-formatting.md#escaping-braces) section of the [Composite formatting](../../standard/base-types/composite-formatting.md) article. diff --git a/docs/index.yml b/docs/index.yml index d09d7011ef4b8..e657475002e70 100644 --- a/docs/index.yml +++ b/docs/index.yml @@ -111,7 +111,7 @@ conceptualContent: # Card - title: Develop .NET apps links: - - url: ai/quickstarts/get-started-openai.md + - url: ai/quickstarts/build-chat-app.md itemType: quickstart text: Build an Azure AI chat app with .NET - url: /dotnet/desktop/wpf/get-started/create-app-visual-studio @@ -316,7 +316,7 @@ additionalContent: links: - url: ai/index.yml text: AI for .NET developers - - url: ai/quickstarts/get-started-openai.md + - url: ai/quickstarts/build-chat-app.md text: Build a chat app - url: ai/conceptual/prompt-engineering-dotnet.md text: Understand prompt engineering diff --git a/docs/whats-new/dotnet-9-release.md b/docs/whats-new/dotnet-9-release.md index 8cc7e34ce8e8a..5981917da009f 100644 --- a/docs/whats-new/dotnet-9-release.md +++ b/docs/whats-new/dotnet-9-release.md @@ -158,7 +158,7 @@ This article lists some of the major changes to docs for .NET 9. - [The history of C\#](../csharp/whats-new/csharp-version-history.md) - Add conceptual content for partial properties - [The lock statement - ensure exclusive access to a shared resource](../csharp/language-reference/statements/lock.md) - Add language reference for `lock` - [Type-testing operators and cast expressions - `is`, `as`, `typeof` and casts](../csharp/language-reference/operators/type-testing-and-cast.md) - Explain better conversion from collection expression -- [Use string interpolation to construct formatted strings](../csharp/tutorials/exploration/interpolated-strings-local.md) - Add conceptual content for partial properties +- [Use string interpolation to construct formatted strings](../csharp/tutorials/string-interpolation.md) - Add conceptual content for partial properties - [Using indexers (C# Programming Guide)](../csharp/programming-guide/indexers/using-indexers.md) - Add conceptual content for partial properties - [Using Properties (C# Programming Guide)](../csharp/programming-guide/classes-and-structs/using-properties.md) - Add conceptual content for partial properties - [where (generic type constraint) (C# Reference)](../csharp/language-reference/keywords/where-generic-type-constraint.md) - Add reference and conceptual content for `ref struct` allowed in interfaces