Pruebas en un entorno real
Pruebe en producción sin marcas de agua.
Funciona donde lo necesites.
Span es un tipo introducido en C# 7.2 como parte del Span
Span en C# permite a los desarrolladores trabajar directamente con la memoria sin recurrir a las tradicionales asignaciones de heap. Ofrece una forma de crear porciones de memoria a partir de matrices existentes u otras fuentes de memoria, eliminando la necesidad de copias de memoria adicionales.
Una de las características más destacadas de C# Span son sus abstracciones de copia cero. En lugar de duplicar datos, Span proporciona una forma de referenciar la memoria existente de forma eficiente. Esto es especialmente beneficioso en situaciones en las que copiar grandes cantidades de datos sería poco práctico o demasiado costoso.
Aunque C# ha sido tradicionalmente un lenguaje de alto nivel y seguro, Span introduce cierto grado de manipulación de memoria de bajo nivel similar al trabajo con punteros en lenguajes como C o C++. Los desarrolladores pueden realizar operaciones de tipo puntero sin sacrificar la seguridad y la naturaleza gestionada de C#.
A pesar de sus capacidades de acceso a memoria de bajo nivel, C# Span sigue siendo inmutable. Esto significa que, aunque permite la manipulación de la memoria, refuerza la seguridad impidiendo modificaciones no intencionadas.
using System;
class Program
{
void Main()
{
int [] array = { 1, 2, 3, 4, 5 };
// Crear un span que apunte a todo el array
Span<int> span = array;
// Modificar los datos utilizando el span
span [2] = 10;
// Imprime la matriz modificada
foreach (var item in array)
{
Console.WriteLine(item);
}
}
}
using System;
class Program
{
void Main()
{
int [] array = { 1, 2, 3, 4, 5 };
// Crear un span que apunte a todo el array
Span<int> span = array;
// Modificar los datos utilizando el span
span [2] = 10;
// Imprime la matriz modificada
foreach (var item in array)
{
Console.WriteLine(item);
}
}
}
Imports System
Friend Class Program
Private Sub Main()
Dim array() As Integer = { 1, 2, 3, 4, 5 }
' Crear un span que apunte a todo el array
Dim span As Span(Of Integer) = array
' Modificar los datos utilizando el span
span (2) = 10
' Imprime la matriz modificada
For Each item In array
Console.WriteLine(item)
Next item
End Sub
End Class
Mientras Span
He aquí algunos puntos clave.
Como su nombre indica, ReadOnlySpan
Como Span
Como Span
Al igual que con Span
ReadOnlySpan
using System;
class Program
{
static void Main()
{
int [] array = { 1, 2, 3, 4, 5 };
// Crear un span de sólo lectura que apunte a todo el array
ReadOnlySpan<int> readOnlySpan = array;
// Acceder e imprimir los datos a través del tramo de sólo lectura
foreach (var item in readOnlySpan)
{
Console.WriteLine(item);
}
// Nota: La siguiente línea daría lugar a un error de compilación ya que readOnlySpan es de sólo lectura.
// readOnlySpan [2] = 10;
}
}
using System;
class Program
{
static void Main()
{
int [] array = { 1, 2, 3, 4, 5 };
// Crear un span de sólo lectura que apunte a todo el array
ReadOnlySpan<int> readOnlySpan = array;
// Acceder e imprimir los datos a través del tramo de sólo lectura
foreach (var item in readOnlySpan)
{
Console.WriteLine(item);
}
// Nota: La siguiente línea daría lugar a un error de compilación ya que readOnlySpan es de sólo lectura.
// readOnlySpan [2] = 10;
}
}
Imports System
Friend Class Program
Shared Sub Main()
Dim array() As Integer = { 1, 2, 3, 4, 5 }
' Crear un span de sólo lectura que apunte a todo el array
Dim readOnlySpan As ReadOnlySpan(Of Integer) = array
' Acceder e imprimir los datos a través del tramo de sólo lectura
For Each item In readOnlySpan
Console.WriteLine(item)
Next item
' Nota: La siguiente línea daría lugar a un error de compilación ya que readOnlySpan es de sólo lectura.
' readOnlySpan [2] = 10;
End Sub
End Class
Hay muchas maneras diferentes de crear ReadOnlySpan y trabajar con él. A continuación figuran algunos ejemplos.
string msg = "Hello, World!";
ReadOnlySpan<char> span1 = msg.AsSpan();
// Manipulación de sólo lectura
char firstChar = span1 [0];
Console.WriteLine(firstChar); // Salidas: H
string msg = "Hello, World!";
ReadOnlySpan<char> span1 = msg.AsSpan();
// Manipulación de sólo lectura
char firstChar = span1 [0];
Console.WriteLine(firstChar); // Salidas: H
Dim msg As String = "Hello, World!"
Dim span1 As ReadOnlySpan(Of Char) = msg.AsSpan()
' Manipulación de sólo lectura
Dim firstChar As Char = span1 (0)
Console.WriteLine(firstChar) ' Salidas: H
Utilizar Slice en el ReadOnlySpan
ReadOnlySpan<char> substringSpan = spanFromString.Slice(startIndex, length);
ReadOnlySpan<char> substringSpan = spanFromString.Slice(startIndex, length);
Dim substringSpan As ReadOnlySpan(Of Char) = spanFromString.Slice(startIndex, length)
Pasar ReadOnlySpan
void ProcessSubstringfromReadOnlySpan(ReadOnlySpan<char> substring)
{
// Realizar operaciones en la subcadena
}
// Utilización
ProcessSubstringfromReadOnlySpan(spanFromString.Slice(startIndex, length));
void ProcessSubstringfromReadOnlySpan(ReadOnlySpan<char> substring)
{
// Realizar operaciones en la subcadena
}
// Utilización
ProcessSubstringfromReadOnlySpan(spanFromString.Slice(startIndex, length));
Private Sub ProcessSubstringfromReadOnlySpan(ByVal substring As ReadOnlySpan(Of Char))
' Realizar operaciones en la subcadena
End Sub
' Utilización
ProcessSubstringfromReadOnlySpan(spanFromString.Slice(startIndex, length))
ReadOnlySpan
int index = stringSpan.IndexOf('W');
int index = stringSpan.IndexOf('W');
Dim index As Integer = stringSpan.IndexOf("W"c)
ReadOnlySpan
using (var memmf = MemoryMappedFile.CreateFromFile("data.bin"))
{
using (var accessor = memmf.CreateViewAccessor())
{
ReadOnlySpan<byte> dataSpan;
accessor.Read(0, out dataSpan);
// Procesar datos directamente desde el archivo mapeado en memoria
ProcessData(dataSpan);
}
}
using (var memmf = MemoryMappedFile.CreateFromFile("data.bin"))
{
using (var accessor = memmf.CreateViewAccessor())
{
ReadOnlySpan<byte> dataSpan;
accessor.Read(0, out dataSpan);
// Procesar datos directamente desde el archivo mapeado en memoria
ProcessData(dataSpan);
}
}
Using memmf = MemoryMappedFile.CreateFromFile("data.bin")
Using accessor = memmf.CreateViewAccessor()
Dim dataSpan As ReadOnlySpan(Of Byte) = Nothing
accessor.Read(0, dataSpan)
' Procesar datos directamente desde el archivo mapeado en memoria
ProcessData(dataSpan)
End Using
End Using
ReadOnlySpan
// Sustituir un carácter de una subcadena sin crear una nueva cadena
spanFromString.Slice(startIndex, length).CopyTo(newSpan);
// Sustituir un carácter de una subcadena sin crear una nueva cadena
spanFromString.Slice(startIndex, length).CopyTo(newSpan);
' Sustituir un carácter de una subcadena sin crear una nueva cadena
spanFromString.Slice(startIndex, length).CopyTo(newSpan)
Cuando se trabaja con bibliotecas externas o API que operan con intervalos de caracteres.
void ExternalApiMethod(ReadOnlySpan<char> data)
{
// Llamar a la API externa con el carácter span
}
// Utilización
ExternalApiMethod(spanFromString.Slice(startIndex, length));
void ExternalApiMethod(ReadOnlySpan<char> data)
{
// Llamar a la API externa con el carácter span
}
// Utilización
ExternalApiMethod(spanFromString.Slice(startIndex, length));
Private Sub ExternalApiMethod(ByVal data As ReadOnlySpan(Of Char))
' Llamar a la API externa con el carácter span
End Sub
' Utilización
ExternalApiMethod(spanFromString.Slice(startIndex, length))
ReadOnlySpan
Aunque Span en C# es una potente función con numerosas ventajas, conlleva ciertas limitaciones y consideraciones, especialmente en el contexto de la memoria contigua y no contigua. Exploremos estas limitaciones:
Span
Desde Span
Span
Span
Mientras Span
Mientras Span
ReadOnlySpan
Ciertas estructuras de datos o escenarios que dependen de memoria no contigua pueden no alinearse bien con ReadOnlySpan
En situaciones que implican memoria no contigua, particularmente aquellas que requieren aritmética de punteros compleja, ReadOnlySpan
Al igual que ocurre con la memoria contigua, es importante tener en cuenta que no todas las API o bibliotecas admiten directamente la memoria no contigua representada por ReadOnlySpan
En C#, Span puede utilizarse eficazmente con memoria no gestionada para realizar operaciones relacionadas con la memoria de forma controlada y eficiente. La memoria no gestionada se refiere a la memoria que no está gestionada por el recolector de basura del tiempo de ejecución de .NET, y a menudo implica el uso de asignaciones y desasignaciones de memoria nativa. He aquí cómo se puede utilizar Span con memoria no gestionada en C#.
Para asignar memoria no gestionada, puede utilizar la clase System.Runtime.InteropServices.MemoryMarshal. El método Marshal.AllocHGlobal asigna memoria y devuelve un puntero al bloque asignado. La memoria asignada o dirección de memoria se mantiene en un puntero unmanagedMemory y tendrá acceso de lectura-escritura. Se puede acceder fácilmente a las regiones contiguas de la memoria.
using System;
using System.Runtime.InteropServices;
class Program
{
static void Main()
{
const int bufferSize = 100;
IntPtr unmanagedMemory = Marshal.AllocHGlobal(bufferSize);
// Crear un Span a partir de la memoria no gestionada
Span<byte> span = new Span<byte>(unmanagedMemory.ToPointer(), bufferSize);
// Utiliza el Span cuando sea necesario...
// No olvides liberar la memoria no gestionada cuando termines
Marshal.FreeHGlobal(unmanagedMemory);
}
}
using System;
using System.Runtime.InteropServices;
class Program
{
static void Main()
{
const int bufferSize = 100;
IntPtr unmanagedMemory = Marshal.AllocHGlobal(bufferSize);
// Crear un Span a partir de la memoria no gestionada
Span<byte> span = new Span<byte>(unmanagedMemory.ToPointer(), bufferSize);
// Utiliza el Span cuando sea necesario...
// No olvides liberar la memoria no gestionada cuando termines
Marshal.FreeHGlobal(unmanagedMemory);
}
}
Imports System
Imports System.Runtime.InteropServices
Friend Class Program
Shared Sub Main()
Const bufferSize As Integer = 100
Dim unmanagedMemory As IntPtr = Marshal.AllocHGlobal(bufferSize)
' Crear un Span a partir de la memoria no gestionada
Dim span As New Span(Of Byte)(unmanagedMemory.ToPointer(), bufferSize)
' Utiliza el Span cuando sea necesario...
' No olvides liberar la memoria no gestionada cuando termines
Marshal.FreeHGlobal(unmanagedMemory)
End Sub
End Class
En el código fuente anterior, asignamos un bloque de memoria no gestionada utilizando Marshal.AllocHGlobal y luego creamos un Span
Span proporciona métodos como Slice, CopyTo y ToArray que pueden utilizarse para copiar datos entre memoria gestionada y no gestionada de forma eficiente.
using System;
using System.Runtime.InteropServices;
class Program
{
static void Main()
{
// Matriz gestionada de la que copiar datos
int [] sourceArray = { 1, 2, 3, 4, 5 };
// Asignar memoria no gestionada para los datos de destino
IntPtr destinationPointer = MemoryMarshal.Allocate<int>(sourceArray.Length);
try
{
// Create a Span<int> from the source array
Span<int> sourceSpan = sourceArray;
// Create a Span<int> from the allocated unmanaged memory
Span<int> destinationSpan = MemoryMarshal.Cast<int, byte>(destinationPointer, sourceArray.Length);
// Copy data from the source Span<int> to the destination Span<int>
sourceSpan.CopyTo(destinationSpan);
// Imprimir los valores de la memoria de destino
Console.WriteLine("Values in the destination memory:");
foreach (var value in destinationSpan)
{
Console.Write($"{value} ");
}
}
finally
{
// Desasignar la memoria no gestionada cuando haya terminado
MemoryMarshal.Free(destinationPointer);
}
}
}
using System;
using System.Runtime.InteropServices;
class Program
{
static void Main()
{
// Matriz gestionada de la que copiar datos
int [] sourceArray = { 1, 2, 3, 4, 5 };
// Asignar memoria no gestionada para los datos de destino
IntPtr destinationPointer = MemoryMarshal.Allocate<int>(sourceArray.Length);
try
{
// Create a Span<int> from the source array
Span<int> sourceSpan = sourceArray;
// Create a Span<int> from the allocated unmanaged memory
Span<int> destinationSpan = MemoryMarshal.Cast<int, byte>(destinationPointer, sourceArray.Length);
// Copy data from the source Span<int> to the destination Span<int>
sourceSpan.CopyTo(destinationSpan);
// Imprimir los valores de la memoria de destino
Console.WriteLine("Values in the destination memory:");
foreach (var value in destinationSpan)
{
Console.Write($"{value} ");
}
}
finally
{
// Desasignar la memoria no gestionada cuando haya terminado
MemoryMarshal.Free(destinationPointer);
}
}
}
Imports System
Imports System.Runtime.InteropServices
Friend Class Program
Shared Sub Main()
' Matriz gestionada de la que copiar datos
Dim sourceArray() As Integer = { 1, 2, 3, 4, 5 }
' Asignar memoria no gestionada para los datos de destino
Dim destinationPointer As IntPtr = MemoryMarshal.Allocate(Of Integer)(sourceArray.Length)
Try
' Create a Span<int> from the source array
Dim sourceSpan As Span(Of Integer) = sourceArray
' Create a Span<int> from the allocated unmanaged memory
Dim destinationSpan As Span(Of Integer) = MemoryMarshal.Cast(Of Integer, Byte)(destinationPointer, sourceArray.Length)
' Copy data from the source Span<int> to the destination Span<int>
sourceSpan.CopyTo(destinationSpan)
' Imprimir los valores de la memoria de destino
Console.WriteLine("Values in the destination memory:")
For Each value In destinationSpan
Console.Write($"{value} ")
Next value
Finally
' Desasignar la memoria no gestionada cuando haya terminado
MemoryMarshal.Free(destinationPointer)
End Try
End Sub
End Class
En este ejemplo:
MemoryMarshal.Allocate
Cuando se trabaja con memoria no gestionada, también se puede utilizar código inseguro con punteros. En tales casos, puede obtener un puntero del Span utilizando el método Unsafe.AsPointer() método.
using System;
using System.Runtime.InteropServices;
class Program
{
static void Main()
{
const int bufferSize = 100;
IntPtr unmanagedMemory = Marshal.AllocHGlobal(bufferSize);
// Crear un Span a partir de la memoria no gestionada
Span<byte> span = new Span<byte>(unmanagedMemory.ToPointer(), bufferSize);
// Utilizar código inseguro para trabajar con punteros
// ref t
unsafe
{
byte* pointer = (byte*)Unsafe.AsPointer(ref struct MemoryMarshal.GetReference(span));
// Utiliza el puntero según necesites...
}
// No olvides liberar la memoria no gestionada cuando termines
Marshal.FreeHGlobal(unmanagedMemory);
}
}
using System;
using System.Runtime.InteropServices;
class Program
{
static void Main()
{
const int bufferSize = 100;
IntPtr unmanagedMemory = Marshal.AllocHGlobal(bufferSize);
// Crear un Span a partir de la memoria no gestionada
Span<byte> span = new Span<byte>(unmanagedMemory.ToPointer(), bufferSize);
// Utilizar código inseguro para trabajar con punteros
// ref t
unsafe
{
byte* pointer = (byte*)Unsafe.AsPointer(ref struct MemoryMarshal.GetReference(span));
// Utiliza el puntero según necesites...
}
// No olvides liberar la memoria no gestionada cuando termines
Marshal.FreeHGlobal(unmanagedMemory);
}
}
Imports System
Imports System.Runtime.InteropServices
Friend Class Program
Shared Sub Main()
Const bufferSize As Integer = 100
Dim unmanagedMemory As IntPtr = Marshal.AllocHGlobal(bufferSize)
' Crear un Span a partir de la memoria no gestionada
Dim span As New Span(Of Byte)(unmanagedMemory.ToPointer(), bufferSize)
' Utilizar código inseguro para trabajar con punteros
' ref t
'INSTANT VB TODO TASK: C# 'unsafe' code is not converted by Instant VB:
' unsafe
' {
' byte* pointer = (byte*)Unsafe.AsPointer(ref struct MemoryMarshal.GetReference(span));
' ' Utiliza el puntero según necesites...
' }
' No olvides liberar la memoria no gestionada cuando termines
Marshal.FreeHGlobal(unmanagedMemory)
End Sub
End Class
En este ejemplo, utilizamos el método Unsafe.AsPointer para obtener un puntero del Span. Esto nos permite utilizar código inseguro cuando trabajamos directamente con punteros.
Recuerde que, cuando se trabaja con memoria no gestionada, es crucial gestionar la asignación y desasignación correctamente para evitar fugas de memoria. Libere siempre la memoria no gestionada utilizando métodos adecuados, como Marshal.FreeHGlobal(). Además, tenga cuidado al utilizar código no seguro, ya que puede introducir posibles riesgos de seguridad si no se maneja adecuadamente.
El uso de Span junto con llamadas a métodos asíncronos en C# es una potente combinación, especialmente cuando se trata de grandes cantidades de datos u operaciones de E/S. El objetivo es manejar las operaciones asíncronas sin copias innecesarias de datos de forma eficiente. Exploremos cómo puede aprovechar Span en escenarios asíncronos:
Cuando se trata de operaciones de E/S asíncronas, como la lectura o escritura de datos en un flujo, puede utilizar Memory
async Task ProcessDataAsync(Stream stream)
{
const int bufferSize = 4096;
byte [] buffer = new byte [bufferSize];
while (true)
{
int bytesRead = await stream.ReadAsync(buffer.AsMemory());
if (bytesRead == 0)
break;
// Procesar los datos mediante Span sin copias innecesarias
ProcessData(buffer.AsSpan(0, bytesRead));
}
}
void ProcessData(Span<byte> data)
{
// Realizar operaciones con los datos
}
async Task ProcessDataAsync(Stream stream)
{
const int bufferSize = 4096;
byte [] buffer = new byte [bufferSize];
while (true)
{
int bytesRead = await stream.ReadAsync(buffer.AsMemory());
if (bytesRead == 0)
break;
// Procesar los datos mediante Span sin copias innecesarias
ProcessData(buffer.AsSpan(0, bytesRead));
}
}
void ProcessData(Span<byte> data)
{
// Realizar operaciones con los datos
}
Async Function ProcessDataAsync(ByVal stream As Stream) As Task
Const bufferSize As Integer = 4096
Dim buffer(bufferSize - 1) As Byte
Do
Dim bytesRead As Integer = Await stream.ReadAsync(buffer.AsMemory())
If bytesRead = 0 Then
Exit Do
End If
' Procesar los datos mediante Span sin copias innecesarias
ProcessData(buffer.AsSpan(0, bytesRead))
Loop
End Function
Private Sub ProcessData(ByVal data As Span(Of Byte))
' Realizar operaciones con los datos
End Sub
En este ejemplo, el método ReadAsync lee asíncronamente datos de un flujo en el búfer. A continuación, el método ProcessData procesa los datos directamente desde el Span
De forma similar a las operaciones de E/S, cuando se trata de operaciones de archivo asíncronas, puede utilizar Span para procesar datos de forma eficiente sin necesidad de realizar copias adicionales.
async Task ProcessFileAsync(string filePath)
{
const int bufferSize = 4096;
using (FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
{
byte [] buffer = new byte [bufferSize];
while (true)
{
int bytesRead = await fileStream.ReadAsync(buffer.AsMemory());
if (bytesRead == 0)
break;
// Procesar los datos mediante Span sin copias innecesarias
ProcessData(buffer.AsSpan(0, bytesRead));
}
}
}
void ProcessData(Span<byte> data)
{
// Realizar operaciones con los datos
}
async Task ProcessFileAsync(string filePath)
{
const int bufferSize = 4096;
using (FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
{
byte [] buffer = new byte [bufferSize];
while (true)
{
int bytesRead = await fileStream.ReadAsync(buffer.AsMemory());
if (bytesRead == 0)
break;
// Procesar los datos mediante Span sin copias innecesarias
ProcessData(buffer.AsSpan(0, bytesRead));
}
}
}
void ProcessData(Span<byte> data)
{
// Realizar operaciones con los datos
}
Async Function ProcessFileAsync(ByVal filePath As String) As Task
Const bufferSize As Integer = 4096
Using fileStream As New FileStream(filePath, FileMode.Open, FileAccess.Read)
Dim buffer(bufferSize - 1) As Byte
Do
Dim bytesRead As Integer = Await fileStream.ReadAsync(buffer.AsMemory())
If bytesRead = 0 Then
Exit Do
End If
' Procesar los datos mediante Span sin copias innecesarias
ProcessData(buffer.AsSpan(0, bytesRead))
Loop
End Using
End Function
Private Sub ProcessData(ByVal data As Span(Of Byte))
' Realizar operaciones con los datos
End Sub
Aquí, el método ReadAsync lee datos de un flujo de archivos en el búfer, y el método ProcessData procesa los datos directamente desde el Span
Cuando se trabaja con tareas asíncronas que producen o consumen datos, se puede utilizar Memory
async Task<int> ProcessDataAsync(int [] data)
{
// Tratamiento asíncrono de datos
await Task.Delay(1000);
// Devuelve la longitud de los datos procesados
return data.Length;
}
async Task Main()
{
int [] inputData = Enumerable.Range(1, 1000).ToArray();
// Procesar los datos de forma asíncrona sin copiarlos
int processedLength = await ProcessDataAsync(inputData.AsMemory());
Console.WriteLine($"Processed data length: {processedLength}");
}
async Task<int> ProcessDataAsync(int [] data)
{
// Tratamiento asíncrono de datos
await Task.Delay(1000);
// Devuelve la longitud de los datos procesados
return data.Length;
}
async Task Main()
{
int [] inputData = Enumerable.Range(1, 1000).ToArray();
// Procesar los datos de forma asíncrona sin copiarlos
int processedLength = await ProcessDataAsync(inputData.AsMemory());
Console.WriteLine($"Processed data length: {processedLength}");
}
Async Function ProcessDataAsync(ByVal data() As Integer) As Task(Of Integer)
' Tratamiento asíncrono de datos
Await Task.Delay(1000)
' Devuelve la longitud de los datos procesados
Return data.Length
End Function
Async Function Main() As Task
Dim inputData() As Integer = Enumerable.Range(1, 1000).ToArray()
' Procesar los datos de forma asíncrona sin copiarlos
Dim processedLength As Integer = Await ProcessDataAsync(inputData.AsMemory())
Console.WriteLine($"Processed data length: {processedLength}")
End Function
En este ejemplo, el método ProcessDataAsync procesa los datos de forma asíncrona y devuelve la longitud de los datos procesados sin necesidad de copias adicionales.
IronPDF es la última biblioteca PDF en C# de Iron Software que puede utilizarse para generar hermosos documentos PDF sobre la marcha de forma dinámica utilizando código C#. IronPDF ofrece diversas funciones, como la generación de PDF a partir de HTML, la conversión de contenido HTML a PDF, la fusión o división de archivos PDF, etc.
IronPDF puede instalarse mediante la aplicación NuGet Package Manager o utilizando el gestor de paquetes de Visual Studio.
dotnet add package IronPdf
// O
Install-Package IronPdf
dotnet add package IronPdf
// O
Install-Package IronPdf
'INSTANT VB TODO TASK: The following line uses invalid syntax:
'dotnet add package IronPdf Install-Package IronPdf
using System;
class Program
{
static void Main()
{
Console.WriteLine("Generating PDF using IronPDF.");
var displayFirstName = "<p>First Name is Joe</p>".AsSpan();
var displayLastName = "<p>First Name is Doe</p>".AsSpan();
var displayAddress = "<p>12th Main, 7Th Cross, New York</p>".AsSpan();
var start = @"<!DOCTYPE html>
<html>
<body>".AsSpan();
var end = @"<!DOCTYPE html>
<html>
<body>";
var content = string.Concat(start, displayFirstName, displayLastName, string.Concat(displayAddress, end));
var pdfDocument = new ChromePdfRenderer();
pdfDocument.RenderHtmlAsPdf(content).SaveAs("span.pdf");
}
}
using System;
class Program
{
static void Main()
{
Console.WriteLine("Generating PDF using IronPDF.");
var displayFirstName = "<p>First Name is Joe</p>".AsSpan();
var displayLastName = "<p>First Name is Doe</p>".AsSpan();
var displayAddress = "<p>12th Main, 7Th Cross, New York</p>".AsSpan();
var start = @"<!DOCTYPE html>
<html>
<body>".AsSpan();
var end = @"<!DOCTYPE html>
<html>
<body>";
var content = string.Concat(start, displayFirstName, displayLastName, string.Concat(displayAddress, end));
var pdfDocument = new ChromePdfRenderer();
pdfDocument.RenderHtmlAsPdf(content).SaveAs("span.pdf");
}
}
Imports System
Friend Class Program
Shared Sub Main()
Console.WriteLine("Generating PDF using IronPDF.")
Dim displayFirstName = "<p>First Name is Joe</p>".AsSpan()
Dim displayLastName = "<p>First Name is Doe</p>".AsSpan()
Dim displayAddress = "<p>12th Main, 7Th Cross, New York</p>".AsSpan()
Dim start = "<!DOCTYPE html>
<html>
<body>".AsSpan()
Dim [end] = "<!DOCTYPE html>
<html>
<body>"
Dim content = String.Concat(start, displayFirstName, displayLastName, String.Concat(displayAddress, [end]))
Dim pdfDocument = New ChromePdfRenderer()
pdfDocument.RenderHtmlAsPdf(content).SaveAs("span.pdf")
End Sub
End Class
En este ejemplo, estamos utilizando Span junto con IronPDF para generar un documento PDF.
Salida:
PDF generado:
IronPDF. Esta clave debe colocarse en appsettings.json.
"IronPdf.LicenseKey": "your license key"
"IronPdf.LicenseKey": "your license key"
'INSTANT VB TODO TASK: The following line uses invalid syntax:
'"IronPdf.LicenseKey": "your license key"
Proporcione su correo electrónico para obtener una licencia de prueba.
Span
Junto con el prueba gratuita para un uso prolongado. Para saber más sobre cómo utilizar IronPDF visite su documentación página.
9 productos API .NET para sus documentos de oficina