Dot Net Framework Es PDF
Dot Net Framework Es PDF
Dot Net Framework Es PDF
NET Framework
#.net
Tabla de contenido
Acerca de 1
Observaciones 2
Versiones 2
.RED 2
Marco Compacto 3
Micro marco 3
Examples 3
Hola mundo en c # 3
Hola mundo en F # 4
Hola Mundo en IL 5
Introducción 7
Observaciones 7
Examples 7
Examples 9
Capítulo 4: ADO.NET 10
Introducción 10
Observaciones 10
Examples 10
Ejecutando sentencias SQL como un comando 10
Capítulo 5: Ajustes 14
Examples 14
Uso en desuso 14
Examples 19
ParseExact 19
TryParse 20
TryParseExact 22
Observaciones 23
Examples 23
Observaciones 26
Examples 26
Parámetros 31
Observaciones 31
Examples 31
VB WriteAllText 31
VB StreamWriter 31
C # StreamWriter 31
C # WriteAllText () 31
C # File.Exists () 32
Observaciones 33
Examples 33
Tarea: WaitAny 35
Tarea.cuando 37
Tarea.Cuando 37
Paralelo.Invocar 38
Paralelo.para cada 38
Paralelo.para 38
Parallel.ForEach en VB.NET 39
Examples 41
Sintaxis 43
Parámetros 43
Examples 43
Borrar un archivo 43
"Toque" una gran cantidad de archivos (para actualizar el último tiempo de escritura) 45
Archivo.Mover 46
Observaciones 48
Examples 48
Enviar una solicitud POST con una carga útil de cadena utilizando System.Net.HttpWebReques 49
Enviar una solicitud POST con una carga útil de cadena utilizando System.Net.WebClient 49
Enviar una solicitud POST con una carga útil de cadena utilizando System.Net.HttpClient 50
Examples 52
Observaciones 53
Examples 53
Cola 54
Apilar 56
Introducción 59
Observaciones 59
Examples 59
Muestra de compilación de IL 59
Capítulo 17: Contextos de sincronización 62
Observaciones 62
Examples 62
Observaciones 64
Examples 64
Precondiciones 64
Postcondiciones 64
Observaciones 68
Examples 68
Examples 69
Cronógrafo 69
Observaciones 72
Examples 72
RijndaelManaged 72
Examples 81
Examples 84
Observaciones 85
Examples 85
Filtros de excepción 87
Examples 90
Opciones de paso 90
Partido en grupos 90
Utilizando 91
Código 91
Salida 91
Observaciones 92
Examples 95
Para principiantes 95
Temporizador de formularios 96
Observaciones 99
Examples 99
Recursos no gestionados 99
Observaciones 101
Examples 101
Observaciones 103
Examples 104
Ejemplos: 106
Cuerdas 107
Sintaxis 109
Examples 109
Observaciones 114
Examples 115
Cómo la inyección de dependencia hace que las pruebas unitarias sean más fáciles 116
Introducción 120
Examples 120
Introducción 121
Observaciones 121
Examples 121
Introducción 124
Sintaxis 124
Observaciones 131
Evaluación perezosa 132
Examples 132
OrderByDescending 133
Contiene 134
Excepto 134
Intersecarse 134
Concat 134
Soltero 135
Último 135
LastOrDefault 135
SingleOrDefault 136
FirstOrDefault 136
Alguna 137
Todos 137
Suma 138
Omitir 139
Tomar 139
SecuenciaEqual 139
De tipo 140
Max 140
Min 140
Promedio 140
Cremallera 141
Distinto 141
Al diccionario 142
Unión 143
ToArray 143
Listar 143
Contar 144
Elemento 144
ElementAtOrDefault 144
SkipWhile 144
TakeWhile 145
DefaultIfEmpty 145
Unirse 146
Emitir 148
Vacío 149
Distancia 149
Repetir 150
Examples 152
Problema 157
Solución 157
Observaciones 159
Examples 159
Observaciones 162
Examples 162
Introducción 164
Examples 164
Parámetros 165
Observaciones 165
Examples 165
Examples 167
Observaciones 171
Examples 171
Nota 172
Introducción 174
Observaciones 174
Examples 174
Observaciones 180
Examples 180
Examples 183
Observaciones 186
Examples 186
Examples 190
Observaciones 194
Examples 194
Usando diferentes fuentes de paquetes Nuget (locales) usando la interfaz de usuario 197
Sintaxis 200
Parámetros 200
Observaciones 201
Examples 201
Reconocimiento asíncrono de voz para dictado de texto libre. 201
Examples 202
Observaciones 205
Examples 205
MailMessage 205
Examples 207
Examples 210
Observaciones 212
Examples 212
Las estructuras heredan de System.ValueType, son tipos de valor y viven en la pila. Cuando 212
Las clases heredadas de System.Object, son tipos de referencia y viven en el montón. Cuand 213
Un enum es un tipo especial de clase. La palabra clave enum le dice al compilador que esta 213
Capítulo 56: Trabajar con SHA1 en C # 216
Introducción 216
Examples 216
Introducción 217
Examples 217
Examples 218
Observaciones 220
Examples 220
Creación eficiente de varios serializadores con tipos derivados especificados dinámicament 221
Creditos 225
Acerca de
You can share this PDF with anyone you feel could benefit from it, downloaded the latest version
from: -net-framework
It is an unofficial and free .NET Framework ebook created for educational purposes. All the
content is extracted from Stack Overflow Documentation, which is written by many hardworking
individuals at Stack Overflow. It is neither affiliated with Stack Overflow nor official .NET
Framework.
The content is released under Creative Commons BY-SA, and the list of contributors to each
chapter are provided in the credits section at the end of this book. Images may be copyright of
their respective owners unless otherwise specified. All trademarks and registered trademarks are
the property of their respective company owners.
Use the content presented in this book at your own risk; it is not guaranteed to be correct nor
accurate, please send your feedback and corrections to [email protected]
https://riptutorial.com/es/home 1
Capítulo 1: Empezando con .NET Framework
Observaciones
.NET Framework es un conjunto de bibliotecas y un tiempo de ejecución, diseñado originalmente
por Microsoft. Todos los programas .NET se compilan en un código de bytes llamado Microsoft
Intermediate Language (MSIL). MSIL se ejecuta mediante Common Language Runtime (CLR).
A continuación puede encontrar varios ejemplos de "Hello World" en varios idiomas que son
compatibles con .NET Framework. "Hello World" es un programa que muestra "Hello World" en el
dispositivo de pantalla. Se utiliza para ilustrar la sintaxis básica para construir un programa de
trabajo. También se puede usar como prueba de cordura para asegurarse de que el compilador
de un idioma, el entorno de desarrollo y el entorno de ejecución estén funcionando correctamente.
Versiones
.RED
1.0 2002-02-13
1.1 2003-04-24
2.0 2005-11-07
3.0 2006-11-06
3.5 2007-11-19
4.0 2010-04-12
4.5 2012-08-15
4.5.1 2013-10-17
4.5.2 2014-05-05
4.6 2015-07-20
4.6.1 2015-11-17
4.6.2 2016-08-02
https://riptutorial.com/es/home 2
Versión Fecha de lanzamiento
4.7 2017-04-05
Marco Compacto
1.0 2000-01-01
2.0 2005-10-01
3.5 2007-11-19
3.7 2009-01-01
3.9 2013-06-01
Micro marco
4.2 2011-10-04
4.3 2012-12-04
4.4 2015-10-20
Examples
Hola mundo en c #
using System;
class Program
{
// The Main() function is the first function to be executed in a program
static void Main()
{
// Write the string "Hello World to the standard out
Console.WriteLine("Hello World");
}
}
https://riptutorial.com/es/home 3
la documentación de .NET Framework para obtener más información.
Introducción a C #
Imports System
Module Program
Public Sub Main()
Console.WriteLine("Hello World")
End Sub
End Module
Hola mundo en F #
open System
[<EntryPoint>]
let main argv =
printfn "Hello World"
0
Introducción a F #
Introducción a PowerShell
https://riptutorial.com/es/home 4
System.Console.WriteLine("Hello World");
namespace HelloWorld;
interface
type
App = class
public
class method Main(args: array of String);
end;
implementation
end.
import clr
from System import Console
Console.WriteLine("Hello World")
Hola Mundo en IL
https://riptutorial.com/es/home 5
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: ret
}
https://riptutorial.com/es/home 6
Capítulo 2: .NET Core
Introducción
.NET Core es una plataforma de desarrollo de propósito general mantenida por Microsoft y la
comunidad .NET en GitHub. Es multiplataforma, es compatible con Windows, macOS y Linux, y
puede usarse en dispositivos, en la nube y en escenarios integrados / IoT.
Cuando piense en .NET Core lo siguiente debería venir a la mente (implementación flexible,
multiplataforma, herramientas de línea de comandos, código abierto).
Otra gran cosa es que incluso si es de código abierto, Microsoft lo está apoyando activamente.
Observaciones
Por sí mismo, .NET Core incluye un único modelo de aplicación, aplicaciones de consola, que es
útil para herramientas, servicios locales y juegos basados en texto. Se han construido modelos de
aplicaciones adicionales sobre .NET Core para ampliar su funcionalidad, como por ejemplo:
• ASP.NET Core
• Windows 10 Universal Windows Platform (UWP)
• Xamarin.Formas
Además, .NET Core implementa la biblioteca estándar de .NET y, por lo tanto, es compatible con
las bibliotecas estándar de .NET.
La biblioteca estándar de .NET es una especificación de API que describe el conjunto consistente
de API de .NET que los desarrolladores pueden esperar en cada implementación de .NET. Las
implementaciones de .NET necesitan implementar esta especificación para ser consideradas
compatibles con la biblioteca estándar de .NET y para admitir las bibliotecas que tienen como
destino la biblioteca estándar de .NET.
Examples
Aplicación de consola básica
https://riptutorial.com/es/home 7
}
https://riptutorial.com/es/home 8
Capítulo 3: Acrónimo de glosario
Examples
.Net acrónimos relacionados
Tenga en cuenta que algunos términos como JIT y GC son lo suficientemente genéricos como
para aplicarse a muchos entornos de lenguaje de programación y tiempos de ejecución.
https://riptutorial.com/es/home 9
Capítulo 4: ADO.NET
Introducción
ADO (ActiveX Data Objects) .Net es una herramienta proporcionada por Microsoft que
proporciona acceso a fuentes de datos como SQL Server, Oracle y XML a través de sus
componentes. Las aplicaciones de front-end de .Net pueden recuperar, crear y manipular datos,
una vez que se conectan a una fuente de datos a través de ADO.Net con los privilegios
adecuados.
ADO.Net proporciona una arquitectura sin conexión. Es un enfoque seguro para interactuar con
una base de datos, ya que la conexión no tiene que mantenerse durante toda la sesión.
Observaciones
Una nota sobre la parametrización de SQL con Parameters.AddWithValue : AddWithValue nunca es
un buen punto de partida. Ese método se basa en inferir el tipo de datos de lo que se pasa. Con
esto, puede terminar en una situación en la que la conversión impide que su consulta utilice un
índice . Tenga en cuenta que algunos tipos de datos de SQL Server, como char / varchar (sin la
"n") o la date , no tienen un tipo de datos .NET correspondiente. En esos casos, se debe usar Add
con el tipo de datos correcto .
Examples
Ejecutando sentencias SQL como un comando
// Most ADO.NET objects are disposable and, thus, require the using keyword.
using (var connection = new SqlConnection(connectionString))
using (var command = new SqlCommand(sql, connection))
{
// Use parameters instead of string concatenation to add user-supplied
// values to avoid SQL injection and formatting issues. Explicitly supply datatype.
https://riptutorial.com/es/home 10
connection.Open();
command.ExecuteNonQuery();
}
{
// best practice - use column names in your INSERT statement so you are not dependent
on the sql schema column order
// best practice - always use parameters to avoid sql injection attacks and errors if
malformed text is used like including a single quote which is the sql equivalent of escaping
or starting a string (varchar/nvarchar)
// best practice - give your parameters meaningful names just like you do variables in
your code
using(SqlCommand sc = new SqlCommand("INSERT INTO employee (FirstName, LastName,
DateOfBirth /*etc*/) VALUES (@firstName, @lastName, @dateOfBirth /*etc*/)", con))
{
// best practice - always specify the database data type of the column you are
using
// best practice - check for valid values in your code and/or use a database
constraint, if inserting NULL then use System.DbNull.Value
sc.Parameters.Add(new SqlParameter("@firstName", SqlDbType.VarChar, 200){Value =
newEmployee.FirstName ?? (object) System.DBNull.Value});
sc.Parameters.Add(new SqlParameter("@lastName", SqlDbType.VarChar, 200){Value =
newEmployee.LastName ?? (object) System.DBNull.Value});
// best practice - always use the correct types when specifying your parameters,
Value is assigned to a DateTime instance and not a string representation of a Date
sc.Parameters.Add(new SqlParameter("@dateOfBirth", SqlDbType.Date){ Value =
newEmployee.DateOfBirth });
// best practice - open your connection as late as possible unless you need to
verify that the database connection is valid and wont fail and the proceeding code execution
takes a long time (not the case here)
con.Open();
sc.ExecuteNonQuery();
}
// the end of the using block will close and dispose the SqlConnection
// best practice - end the using block as soon as possible to release the database
connection
}
https://riptutorial.com/es/home 11
}
https://riptutorial.com/es/home 12
Server puede reutilizar los planes de ejecución si los parámetros coinciden en tipo y
tamaño. Usa -1 para MAX
○No utilice el método AddWithValue , la razón principal es que es muy fácil olvidar
especificar el tipo de parámetro o la precisión / escala cuando sea necesario. Para
información adicional, vea ¿Podemos dejar de usar AddWithValue ya?
• Cuando se utilizan conexiones de base de datos
○Abra la conexión lo más tarde posible y ciérrela tan pronto como sea posible. Esta es
una guía general cuando se trabaja con cualquier recurso externo
○Nunca comparta instancias de conexión de base de datos (ejemplo: tener un host
singleton una instancia compartida de tipo SqlConnection ). Haga que su código
siempre cree una nueva instancia de conexión de base de datos cuando sea
necesario y luego haga que el código de llamada lo elimine y "deséchelo" cuando
termine. La razón de esto es
○ La mayoría de los proveedores de bases de datos tienen algún tipo de
agrupación de conexiones, por lo que crear nuevas conexiones administradas es
barato
○ Elimina cualquier error futuro si el código comienza a trabajar con varios
subprocesos
https://riptutorial.com/es/home 13
Capítulo 5: Ajustes
Examples
AppSettings de ConfigurationSettings en .NET 1.x
Uso en desuso
Si tiene dos claves con el mismo nombre en la sección de appSettings de la aplicación del archivo
de configuración, se utilizará la última.
app.config
Programa.cs
using System;
using System.Configuration;
using System.Diagnostics;
namespace ConsoleApplication1
{
class Program
{
static void Main()
{
string keyValue = ConfigurationSettings.AppSettings["keyName"];
Debug.Assert("anything, as a string".Equals(keyValue));
Console.ReadKey();
}
}
}
https://riptutorial.com/es/home 14
La clase ConfigurationManager es compatible con la propiedad AppSettings , que le permite
continuar leyendo la configuración de la sección de configuración de la appSettings de un archivo
de configuración de la misma manera que con .NET 1.x.
app.config
Programa.cs
using System;
using System.Configuration;
using System.Diagnostics;
namespace ConsoleApplication1
{
class Program
{
static void Main()
{
string keyValue = ConfigurationManager.AppSettings["keyName"];
Debug.Assert("anything, as a string".Equals(keyValue));
Console.ReadKey();
}
}
}
1. Los ajustes se pueden hacer fuertemente tipados. Cualquier tipo que pueda ser serializado
puede usarse para un valor de configuración.
https://riptutorial.com/es/home 15
user.configen la carpeta de datos de la aplicación del usuario (que varía con la versión del
sistema operativo).
En la mayoría de los tipos de proyectos, el Diseñador de propiedades del proyecto tiene una
pestaña Configuración, que es el punto de partida para crear aplicaciones personalizadas y
configuraciones de usuario. Inicialmente, la pestaña Configuración estará en blanco, con un solo
enlace para crear un archivo de configuración predeterminado. Al hacer clic en los resultados del
enlace en estos cambios:
4. Se agrega un nuevo archivo con una nueva clase parcial en la carpeta Properties en la
carpeta del proyecto. Este nuevo archivo se llama Settings.Designer.__ (.cs, .vb, etc.), y la
clase se llama Settings . La clase es generada por código, por lo que no debe editarse, pero
la clase es una clase parcial, por lo que puede extender la clase poniendo miembros
adicionales en un archivo separado. Además, la clase se implementa utilizando el patrón
Singleton, exponiendo la instancia de singleton con la propiedad denominada Default .
A medida que agrega cada nueva entrada a la pestaña Configuración, Visual Studio hace estas
dos cosas:
https://riptutorial.com/es/home 16
Agregue una configuración de aplicación llamada ExampleTimeout, usando la hora
System.Timespan, y establezca el valor en 1 minuto:
Guarde las Propiedades del proyecto, que guarda las entradas de la pestaña Configuración, y
vuelve a generar la clase de Configuración personalizada y actualiza el archivo de configuración
del proyecto.
Programa.cs
using System;
using System.Diagnostics;
using ConsoleApplication1.Properties;
namespace ConsoleApplication1
{
class Program
{
static void Main()
{
TimeSpan exampleTimeout = Settings.Default.ExampleTimeout;
Debug.Assert(TimeSpan.FromMinutes(1).Equals(exampleTimeout));
Console.ReadKey();
}
}
}
https://riptutorial.com/es/home 17
Debajo de las sábanas
Busque en el archivo de configuración del proyecto para ver cómo se ha creado la entrada de
configuración de la aplicación:
Mire en la clase Settings para ver cómo usa la clase ConfigurationManager para leer esta sección
personalizada.
...
[global::System.Configuration.ApplicationScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("00:01:00")]
public global::System.TimeSpan ExampleTimeout {
get {
return ((global::System.TimeSpan)(this["ExampleTimeout"]));
}
}
...
https://riptutorial.com/es/home 18
Capítulo 6: Análisis DateTime
Examples
ParseExact
Tenga en cuenta que pasar CultureInfo.CurrentCulture como tercer parámetro es idéntico a pasar
null . O bien, puede pasar una cultura específica.
Formato de cadenas
La cadena de entrada puede estar en cualquier formato que coincida con la cadena de formato
24/11/2015 11:01:30 AM
Tenga en cuenta que los valores de mes y minuto se analizaron en los destinos incorrectos.
Las cadenas de formato de un solo carácter deben ser uno de los formatos estándar.
Excepciones
https://riptutorial.com/es/home 19
ArgumentNullException
FormatException
// Format strings must match the input exactly* (see next section)
var date = DateTime.ParseExact("2015-11-24", "d", null); // Expects 11/24/2015 or 24/11/2015
for most cultures
TryParse
Este método acepta una cadena como entrada, intenta analizarla en un DateTime y devuelve un
resultado booleano que indica éxito o fracaso. Si la llamada se realiza correctamente, la variable
que se pasa como parámetro de out se completa con el resultado analizado.
Si el análisis falla, la variable que se pasa como parámetro de out se establece en el valor
predeterminado, DateTime.MinValue .
DateTime parsedValue;
https://riptutorial.com/es/home 20
if (DateTime.TryParse("monkey", out parsedValue))
{
Console.WriteLine("Apparently, 'monkey' is a date/time value. Who knew?");
}
Este método intenta analizar la cadena de entrada según la configuración regional del sistema y
los formatos conocidos, como ISO 8601 y otros formatos comunes.
Dado que este método no acepta información de cultura, utiliza la configuración regional del
sistema. Esto puede llevar a resultados inesperados.
Falso
Falso
Cierto
Tenga en cuenta que si se encuentra en EE. UU., Le sorprenderá que el resultado analizado sea
el 10 de noviembre, no el 11 de octubre.
Excepciones
https://riptutorial.com/es/home 21
Tenga en cuenta que es posible que este método arroje una excepción bajo ciertas condiciones.
Estos se relacionan con los parámetros introducidos para esta sobrecarga: IFormatProvider y
DateTimeStyles .
TryParseExact
Este método se comporta como una combinación de TryParse y ParseExact : permite que se
especifiquen formatos personalizados y devuelve un resultado booleano que indica el éxito o el
fracaso en lugar de lanzar una excepción si el análisis falla.
Esta sobrecarga intenta analizar la cadena de entrada en una matriz de formatos. La cadena de
entrada debe coincidir con al menos un formato para ser analizada.
https://riptutorial.com/es/home 22
Capítulo 7: Apilar y Montar
Observaciones
Vale la pena señalar que al declarar un tipo de referencia, su valor inicial será null . Esto se debe
a que aún no apunta a una ubicación en la memoria, y es un estado perfectamente válido.
Sin embargo, con la excepción de los tipos anulables, los tipos de valor normalmente siempre
deben tener un valor.
Examples
Tipos de valor en uso
Todos los tipos de valor se derivan de la clase System.ValueType , y esto incluye la mayoría de
los tipos integrados.
El siguiente código muestra un tipo de valor que se asigna a una nueva variable. Se está
utilizando una estructura como una forma conveniente de crear un tipo de valor personalizado (la
clase System.ValueType no se puede ampliar de otra manera).
Lo importante a entender es que al asignar un tipo de valor, el valor se copia a la nueva variable,
lo que significa que tenemos dos instancias distintas del objeto, que no pueden afectarse entre sí.
struct PersonAsValueType
{
public string Name;
}
class Program
{
static void Main()
{
PersonAsValueType personA;
personA.Name = "Bob";
personA.Name = "Linda";
https://riptutorial.com/es/home 23
personB));
Además del espacio de memoria requerido para la instancia en sí, se requiere espacio adicional
para almacenar la referencia en sí, junto con la información temporal adicional requerida por el
CLR de .NET.
El siguiente código muestra un tipo de referencia que se asigna a una nueva variable. En este
caso, estamos usando una clase, todas las clases son tipos de referencia (incluso si son
estáticas).
Cuando se asigna un tipo de referencia a otra variable, es la referencia al objeto que se copia, no
el valor en sí. Esta es una distinción importante entre los tipos de valor y los tipos de referencia.
Las implicaciones de esto son que ahora tenemos dos referencias al mismo objeto.
Cualquier cambio en los valores dentro de ese objeto será reflejado por ambas variables.
class PersonAsReferenceType
{
public string Name;
}
class Program
{
static void Main()
{
PersonAsReferenceType personA;
personA.Name = "Linda";
https://riptutorial.com/es/home 24
personB));
https://riptutorial.com/es/home 25
Capítulo 8: Arboles de expresion
Observaciones
Los árboles de expresiones son estructuras de datos que se utilizan para representar expresiones
de código en .NET Framework. Se pueden generar por código y atravesar programáticamente
para traducir el código a otro idioma o ejecutarlo. El generador más popular de Expression Trees
es el compilador de C #. El compilador de C # puede generar árboles de expresión si una
expresión lambda se asigna a una variable de tipo Expresión <Func <... >>. Normalmente esto
sucede en el contexto de LINQ. El consumidor más popular es el proveedor LINQ de Entity
Framework. Consume los árboles de expresión dados a Entity Framework y genera un código
SQL equivalente que luego se ejecuta contra la base de datos.
Examples
Árbol de expresión simple generado por el compilador de C #
La raíz del árbol es la expresión lambda que contiene un cuerpo y una lista de parámetros. La
lambda tiene 1 parámetro llamado "a". El cuerpo es una expresión única del tipo CLR
BinaryExpression y NodeType of Add. Esta expresión representa la suma. Tiene dos
subexpresiones denotadas como Izquierda y Derecha. La izquierda es la expresión de parámetro
para el parámetro "a" y la derecha es una expresión constante con el valor 1.
https://riptutorial.com/es/home 26
Func<int, int> lambda = expression.Compile();
Console.WriteLine(lambda(2)); //prints 3
Por lo general, las expresiones se traducen a otros idiomas como SQL, pero también se pueden
usar para invocar miembros privados, protegidos e internos de tipos públicos o no públicos como
alternativa a Reflection.
Para construir una expresión como _ => _.Field == "VALUE" en tiempo de ejecución.
Dado un predicado _ => _.Field y un valor de cadena "VALUE" , cree una expresión que
compruebe si el predicado es verdadero o no.
Este método construirá una expresión Equal apropiada que compruebe si el Field es o no igual a
"VALUE" .
public TestClass
{
public static string StaticPublicField = "StaticPublicFieldValue";
}
https://riptutorial.com/es/home 27
var fieldExpr = Expression.Field(null, typeof(TestClass), "StaticPublicField");
var labmda = Expression.Lambda<Func<string>>(fieldExpr);
Entonces puede ser compilado en un delegado para recuperar el valor del campo.
Problema Queremos incluir los elementos que tienen "automóvil" en su descripción. Necesitamos
verificarlo en nulo antes de buscar una cadena interna, pero no queremos que se llame en
exceso, ya que el cálculo podría ser costoso.
using System;
using System.Linq;
using System.Linq.Expressions;
Console.WriteLine(elementIsInterestingExpression.ToString());
var countExpensiveComputations = 0;
Action incCount = () => countExpensiveComputations++;
elements
.Where(
CreateSearchPredicate(
"car",
https://riptutorial.com/es/home 28
(Element e) => ExpensivelyComputed(
e, incCount
)
).Compile()
)
.Count();
Salida
https://riptutorial.com/es/home 29
Lo primero que se debe tener en cuenta es cómo el acceso real a la propiedad, envuelto en una
Invocación:
, y esta es la única parte que toca e.Description , y en lugar de ello, el parámetro extracted de tipo
string se pasa a la siguiente:
Otra cosa importante a tener en cuenta aquí es AndAlso . Calcula solo la parte izquierda, si la
primera parte devuelve "falso". Es un error común utilizar el operador bit a bit 'And' en lugar de
este, que siempre calcula ambas partes y fallaría con una NullReferenceException en este
ejemplo.
https://riptutorial.com/es/home 30
Capítulo 9: Archivo de entrada / salida
Parámetros
Parámetro Detalles
Observaciones
Devuelve verdadero si el archivo existe, falso de lo contrario.
Examples
VB WriteAllText
Imports System.IO
VB StreamWriter
C # StreamWriter
using System.Text;
using System.IO;
C # WriteAllText ()
using System.IO;
using System.Text;
https://riptutorial.com/es/home 31
string filename = "c:\path\to\file.txt";
File.writeAllText(filename, "Text to write\n");
C # File.Exists ()
using System;
using System.IO;
if(File.Exists(filePath))
{
Console.WriteLine("Exists");
}
else
{
Console.WriteLine("Does not exist");
}
}
}
https://riptutorial.com/es/home 32
Capítulo 10: Biblioteca paralela de tareas
(TPL)
Observaciones
• Mantener una interfaz de usuario sensible ejecutando el trabajo en segundo plano en una
tarea separada
• Distribuyendo carga de trabajo
• Permitir que una aplicación cliente envíe y reciba solicitudes al mismo tiempo (resto, TCP /
UDP, ect)
• Leyendo y / o escribiendo múltiples archivos a la vez
* El código debe considerarse caso por caso para multiproceso. Por ejemplo, si un bucle solo
tiene unas pocas iteraciones o solo una pequeña parte del trabajo, la sobrecarga para el
paralelismo puede superar los beneficios.
El TPL también está disponible para .Net 3.5 incluido en un paquete NuGet, se llama Task
Parallel Library.
Examples
Bucle básico productor-consumidor (BlockingCollection)
https://riptutorial.com/es/home 33
Vale la pena señalar que si no llama a collection.CompleteAdding(); , puede seguir agregando a la
colección incluso si su tarea de consumidor se está ejecutando. Simplemente llame a
collection.CompleteAdding(); Cuando estés seguro no hay más adiciones. Esta funcionalidad se
puede usar para hacer un patrón de Productor múltiple a un Consumidor único en el que tenga
múltiples fuentes que alimenten elementos en la Colección de Bloqueo y un consumidor individual
extraiga los elementos y haga algo con ellos. Si su BlockingCollection está vacía antes de
completar la adición, Enumerable from collection.GetConsumingEnumerable() se bloqueará hasta
que se agregue un nuevo elemento a la colección o BlockingCollection.CompleteAdding (); se
llama y la cola está vacía.
Task.WaitAll(producerTask, consumerTask);
Console.WriteLine("Everything completed!");
Se puede crear una tarea directamente creando una instancia de la clase de Task ...
Console.WriteLine("Starting task...");
task.Start();
task.Wait();
Console.WriteLine("Task completed!");
Console.WriteLine("Starting task...");
var task = Task.Run(() =>
{
Console.WriteLine("Task code starting...");
Thread.Sleep(2000);
Console.WriteLine("...task code ending!");
});
task.Wait();
Console.WriteLine("Task completed!");
Tenga en cuenta que solo en el primer caso es necesario invocar explícitamente el Start .
https://riptutorial.com/es/home 34
Tarea: WaitAll y captura de variables.
Tarea: WaitAny
while(pendingTasks.Length > 0)
{
var finishedTask = pendingTasks[Task.WaitAny(pendingTasks)];
Console.WriteLine("Task {0} finished", finishedTask.Result);
pendingTasks = pendingTasks.Except(new[] {finishedTask}).ToArray();
}
Task.WaitAll(allTasks);
Nota: el WaitAll final es necesario porque WaitAny no hace que se observen excepciones.
Console.WriteLine("Starting tasks...");
try
{
Task.WaitAll(task1, task2);
}
catch(AggregateException ex)
{
Console.WriteLine("Task(s) failed!");
foreach(var inner in ex.InnerExceptions)
Console.WriteLine(inner.Message);
https://riptutorial.com/es/home 35
}
Console.WriteLine("Starting tasks...");
while(tasks.All(task => !task.IsCompleted));
https://riptutorial.com/es/home 36
cancellationTokenSource.Cancel();
try
{
task.Wait();
}
catch(AggregateException ex)
{
ex.Handle(inner => inner is OperationCanceledException);
}
Tarea.cuando
await Task.WhenAll(tasks);
Console.WriteLine("All tasks finished!");
Tarea.Cuando
https://riptutorial.com/es/home 37
{
Console.WriteLine("I'm task " + n);
return n;
}));
Paralelo.Invocar
try
{
Parallel.Invoke(actions);
}
catch(AggregateException ex)
{
foreach(var inner in ex.InnerExceptions)
Console.WriteLine("Task failed: " + inner.Message);
}
Paralelo.para cada
Este ejemplo utiliza Parallel.ForEach para calcular la suma de los números entre 1 y 10000
mediante el uso de varios subprocesos. Para lograr la seguridad de subprocesos, Interlocked.Add
se utiliza para sumar los números.
using System.Threading;
int Foo()
{
int total = 0;
var numbers = Enumerable.Range(1, 10000).ToList();
Parallel.ForEach(numbers,
() => 0, // initial value,
(num, state, localSum) => num + localSum,
localSum => Interlocked.Add(ref total, localSum));
return total; // total = 50005000
}
Paralelo.para
Este ejemplo utiliza Parallel.For para calcular la suma de los números entre 1 y 10000 mediante
el uso de varios subprocesos. Para lograr la seguridad de subprocesos, Interlocked.Add se utiliza
para sumar los números.
https://riptutorial.com/es/home 38
using System.Threading;
int Foo()
{
int total = 0;
Parallel.For(1, 10001,
() => 0, // initial value,
(num, state, localSum) => num + localSum,
localSum => Interlocked.Add(ref total, localSum));
return total; // total = 50005000
}
Cuando necesite pasar algunos datos de la tarea principal a sus tareas AsyncLocal , para que fluya
lógicamente con la ejecución, use la clase AsyncLocal :
void Main()
{
AsyncLocal<string> user = new AsyncLocal<string>();
user.Value = "initial user";
// this does not affect other tasks - values are local relative to the branches of
execution flow
Task.Run(() => user.Value = "user from another task");
Task.Run(() =>
{
// outputs "user from task1" - value has flown from main method to task1
// than value was changed and flown to this task.
Console.WriteLine(user.Value);
}).Wait();
});
task1.Wait();
// ouputs "initial user" - changes do not propagate back upstream the execution flow
Console.WriteLine(user.Value);
}
Nota: Como puede verse en el ejemplo anterior, AsynLocal.Value tiene copy on read semántica,
pero si fluye algún tipo de referencia y cambia sus propiedades, afectará a otras tareas. Por lo
tanto, la mejor práctica con AsyncLocal es usar tipos de valor o tipos inmutables.
Parallel.ForEach en VB.NET
https://riptutorial.com/es/home 39
For Each row As DataRow In FooDataTable.Rows
Me.RowsToProcess.Add(row)
Next
La tarea que devuelve un valor tiene un tipo de retorno Task< TResult > donde TResult es el tipo
de valor que debe devolverse. Puede consultar el resultado de una tarea por su propiedad
Resultado.
return sum;
});
https://riptutorial.com/es/home 40
Capítulo 11: Cargar archivo y datos POST al
servidor web
Examples
Subir archivo con WebRequest
Para enviar un archivo y datos de formulario en una sola solicitud, el contenido debe tener un tipo
de datos multiparte / formulario .
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Threading.Tasks;
await writer.FlushAsync();
using (var fileStream = File.OpenRead(filename))
await fileStream.CopyToAsync(requestStream);
await writer.WriteAsync($"\r\n--{boundary}--\r\n");
}
https://riptutorial.com/es/home 41
Uso:
var response = await uploader.UploadFile("< YOUR URL >", "< PATH TO YOUR FILE >",
new Dictionary<string, object>
{
{"Comment", "test"},
{"Modified", DateTime.Now }
});
https://riptutorial.com/es/home 42
Capítulo 12: Clase System.IO.File
Sintaxis
• fuente de cadena
• cadena de destino;
Parámetros
Parámetro Detalles
El directorio al que desea mover la source (esta variable también debe contener
destination
el nombre (y la extensión del archivo) del archivo).
Examples
Borrar un archivo
File.Delete(path);
Tenga en cuenta que el último punto (el archivo no existe) generalmente se evita con un
fragmento de código como este:
if (File.Exists(path))
File.Delete(path);
Sin embargo, no es una operación atómica y el archivo puede ser eliminado por otra persona
entre la llamada a File.Exists() y antes de File.Delete() . El enfoque correcto para manejar la
operación de E / S requiere un manejo de excepciones (asumiendo que se puede tomar un curso
alternativo de acciones cuando falla la operación):
if (File.Exists(path))
https://riptutorial.com/es/home 43
{
try
{
File.Delete(path);
}
catch (IOException exception)
{
if (!File.Exists(path))
return; // Someone else deleted this file
Tenga en cuenta que estos errores de E / S a veces son transitorios (archivo en uso, por ejemplo)
y si se trata de una conexión de red, puede recuperarse automáticamente sin ninguna acción por
nuestra parte. Entonces es común volver a intentar una operación de E / S varias veces con un
pequeño retraso entre cada intento:
if (i == NumberOfAttempts)
throw;
Thread.Sleep(DelayBetweenEachAttempt);
}
https://riptutorial.com/es/home 44
Eliminar líneas no deseadas de un archivo de texto
Cambiar un archivo de texto no es fácil porque su contenido debe moverse. Para los archivos
pequeños , el método más sencillo es leer su contenido en la memoria y luego volver a escribir el
texto modificado.
En este ejemplo leemos todas las líneas de un archivo y soltamos todas las líneas en blanco,
luego escribimos de nuevo en la ruta original:
File.WriteAllLines(path,
File.ReadAllLines(path).Where(x => !String.IsNullOrWhiteSpace(x)));
File.WriteAllLines(outputPath,
File.ReadLines(inputPath).Where(x => !String.IsNullOrWhiteSpace(x)));
El texto se guarda codificado (consulte también el tema Cadenas ). A veces, es posible que deba
cambiar su codificación. En este ejemplo se supone (para simplificar) que el archivo no es
demasiado grande y se puede leer por completo en la memoria:
Al realizar conversiones, no olvide que el archivo puede contener BOM (Byte Order Mark), para
comprender mejor cómo se gestiona, consulte Encoding.UTF8.GetString no tiene en cuenta el
Preámbulo / BOM .
Este ejemplo actualiza el último tiempo de escritura de una gran cantidad de archivos (usando
System.IO.Directory.EnumerateFiles lugar de System.IO.Directory.GetFiles() ). Opcionalmente,
puede especificar un patrón de búsqueda (el valor predeterminado es "*.*" Y, finalmente, buscar
en un árbol de directorios (no solo el directorio especificado):
https://riptutorial.com/es/home 45
File.SetLastWriteTime(filePath, now);
}
}
Este fragmento de código es una función auxiliar para enumerar todos los archivos anteriores a
una edad especificada, es útil, por ejemplo, cuando tiene que eliminar archivos de registro
antiguos o datos en caché antiguos.
Archivo.Mover
Para mover un archivo de una ubicación a otra, una simple línea de código puede lograr esto:
File.Move(@"C:\TemporaryFile.txt", @"C:\TemporaryFiles\TemporaryFile.txt");
Sin embargo, hay muchas cosas que podrían salir mal con esta simple operación. Por ejemplo,
¿qué sucede si el usuario que ejecuta su programa no tiene una unidad que tiene la etiqueta 'C'?
¿Qué pasaría si lo hicieran, pero decidieron cambiarle el nombre a 'B' o 'M'?
https://riptutorial.com/es/home 46
¿Qué sucede si el archivo de origen (el archivo en el que desea mover) se ha movido sin que
usted lo sepa, o si simplemente no existe?
Esto asegurará que, en ese mismo momento, el archivo exista y se pueda mover a otra ubicación.
Puede haber ocasiones en que una simple llamada a File.Exists no sea suficiente. Si no es así,
verifique nuevamente, transmita al usuario que la operación falló, o maneje la excepción.
https://riptutorial.com/es/home 47
Capítulo 13: Clientes HTTP
Observaciones
Los RFC HTTP / 1.1 actualmente relevantes son:
Y el experimental RFC:
Protocolos relacionados:
Examples
Leyendo la respuesta GET como una cadena usando
System.Net.HttpWebRequest
https://riptutorial.com/es/home 48
Leyendo la respuesta GET como una cadena usando System.Net.WebClient
Enviar una solicitud POST con una carga útil de cadena utilizando
System.Net.HttpWebRequest
Enviar una solicitud POST con una carga útil de cadena utilizando
System.Net.WebClient
https://riptutorial.com/es/home 49
string requestMethod = "POST";
byte[] responseBody;
byte[] requestBodyBytes = Encoding.UTF8.GetBytes(requestBodyString);
Enviar una solicitud POST con una carga útil de cadena utilizando
System.Net.HttpClient
using System;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
class HttpGet
{
private static async Task DownloadAsync(string fromUrl, string toFile)
{
using (var fileStream = File.OpenWrite(toFile))
{
using (var httpClient = new HttpClient())
{
Console.WriteLine("Connecting...");
using (var networkStream = await httpClient.GetStreamAsync(fromUrl))
{
Console.WriteLine("Downloading...");
await networkStream.CopyToAsync(fileStream);
await fileStream.FlushAsync();
https://riptutorial.com/es/home 50
}
}
}
}
Console.WriteLine("Done!");
}
}
https://riptutorial.com/es/home 51
Capítulo 14: CLR
Examples
Una introducción a Common Language Runtime
El código que se ejecuta en el CLR se conoce como código administrado para distinguirlo del
código que se ejecuta fuera del CLR (generalmente código nativo) que se conoce como código no
administrado . Existen varios mecanismos que facilitan la interoperabilidad entre el código
administrado y el no administrado.
https://riptutorial.com/es/home 52
Capítulo 15: Colecciones
Observaciones
Hay varios tipos de colección:
• Array
• List
• Queue
• SortedList
• Stack
• Diccionario
Examples
Creando una lista inicializada con tipos personalizados
Aquí tenemos una Clase sin constructor con dos propiedades: Name y una propiedad booleana
anulable Selected . Si quisiéramos inicializar una List<Model> , hay varias maneras diferentes de
ejecutar esto.
Aquí, estamos creando varias instancias new de nuestra clase de Model , y las estamos
inicializando con datos. ¿Qué pasa si agregamos un constructor?
https://riptutorial.com/es/home 53
Esto nos permite inicializar nuestra Lista de manera un poco diferente.
¿Qué pasa con una clase donde una de las propiedades es una clase en sí misma?
Observe que revertimos el constructor en la clase Model para simplificar un poco el ejemplo.
Cola
Hay una colección en .Net que se utiliza para administrar valores en una Queue que utiliza el
concepto FIFO (primero en entrar, primero en salir) . Los conceptos básicos de las colas es el
método Enqueue(T item) que se usa para agregar elementos en la cola y Dequeue() que se usa para
obtener el primer elemento y eliminarlo de la cola. La versión genérica se puede utilizar como el
siguiente código para una cola de cadenas.
https://riptutorial.com/es/home 54
Primero, agregue el espacio de nombres:
using System.Collections.Generic;
y úsalo:
string dequeueValue;
dequeueValue = queue.Dequeue(); // return John
dequeueValue = queue.Dequeue(); // return Paul
dequeueValue = queue.Dequeue(); // return George
dequeueValue = queue.Dequeue(); // return Ringo
Existe una versión no genérica del tipo, que funciona con objetos.
using System.Collections;
object dequeueValue;
dequeueValue = queue.Dequeue(); // return Hello World (string)
dequeueValue = queue.Dequeue(); // return 5 (int)
dequeueValue = queue.Dequeue(); // return 1d (double)
dequeueValue = queue.Dequeue(); // return true (bool)
dequeueValue = queue.Dequeue(); // return Product (Product type)
También hay un método llamado Peek () que devuelve el objeto al principio de la cola sin eliminar
los elementos.
https://riptutorial.com/es/home 55
La salida (sin quitar):
10
20
30
40
50
Apilar
Hay una colección en .Net utilizada para administrar valores en una Stack que usa el concepto
LIFO (último en entrar, primero en salir) . Los conceptos básicos de las pilas es el método Push(T
item) que se usa para agregar elementos en la pila y Pop() que se usa para obtener el último
elemento agregado y eliminarlo de la pila. La versión genérica se puede utilizar como el siguiente
código para una cola de cadenas.
using System.Collections.Generic;
y úsalo:
string value;
value = stack.Pop(); // return Ringo
value = stack.Pop(); // return George
value = stack.Pop(); // return Paul
value = stack.Pop(); // return John
Existe una versión no genérica del tipo, que funciona con objetos.
using System.Collections;
object value;
value = stack.Pop(); // return Product (Product type)
value = stack.Pop(); // return true (bool)
https://riptutorial.com/es/home 56
value = stack.Pop(); // return 1d (double)
value = stack.Pop(); // return 5 (int)
value = stack.Pop(); // return Hello World (string)
También hay un método llamado Peek () que devuelve el último elemento agregado pero sin
eliminarlo de la Stack .
Es posible iterar sobre los elementos en la pila y respetará el orden de la pila (LIFO).
50
40
30
20
10
Para colecciones complejas como la clase Dictionary<TKey, TValue> , que toman pares clave /
valor, puede especificar cada par clave / valor como un tipo anónimo en la lista de inicializadores.
https://riptutorial.com/es/home 57
Dictionary<int, string> employee = new Dictionary<int, string>()
{{44, "John"}, {45, "Bob"}, {47, "James"}, {48, "Franklin"}};
https://riptutorial.com/es/home 58
Capítulo 16: Compilador JIT
Introducción
La compilación JIT, o compilación justo a tiempo, es un enfoque alternativo para la interpretación
del código o la compilación anticipada. La compilación JIT se utiliza en el marco .NET. El código
CLR (C #, F #, Visual Basic, etc.) primero se compila en algo llamado Lenguaje interpretado o IL.
Este es un código de nivel inferior que está más cerca del código de la máquina, pero no es
específico de la plataforma. Más bien, en tiempo de ejecución, este código se compila en código
de máquina para el sistema relevante.
Observaciones
¿Por qué usar la compilación JIT?
• Mejor compatibilidad: cada lenguaje CLR necesita solo un compilador para IL, y esta IL
puede ejecutarse en cualquier plataforma en la que se pueda convertir en código de
máquina.
• Velocidad: la compilación JIT intenta combinar la velocidad de ejecución del código
compilado anticipado y la flexibilidad de interpretación (puede analizar el código que se
ejecutará para posibles optimizaciones antes de compilar)
Página de Wikipedia para obtener más información sobre la compilación JIT en general:
https://en.wikipedia.org/wiki/Just-in-time_compilation
Examples
Muestra de compilación de IL
using System;
namespace HelloWorld
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World");
}
}
}
https://riptutorial.com/es/home 59
// Copyright (c) Microsoft Corporation. All rights reserved.
63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 ) // ceptionThrows.
// --- The following custom attribute is added automatically, do not uncomment -------
// .custom instance void [mscorlib]System.Diagnostics.DebuggableAttribute::.ctor(valuetype
[mscorlib]System.Diagnostics.DebuggableAttribute/DebuggingModes) = ( 01 00 07 01 00 00 00 00 )
20 32 30 31 37 00 00 ) // 2017..
.custom instance void [mscorlib]System.Reflection.AssemblyTrademarkAttribute::.ctor(string)
= ( 01 00 00 00 00 )
.custom instance void
[mscorlib]System.Runtime.InteropServices.ComVisibleAttribute::.ctor(bool) = ( 01 00 00 00 00 )
2D 34 30 32 32 2D 61 66 63 63 2D 33 66 38 65 33 // -4022-afcc-3f8e3
32 33 33 63 35 62 30 00 00 ) // 233c5b0..
.custom instance void
[mscorlib]System.Reflection.AssemblyFileVersionAttribute::.ctor(string) = ( 01 00 07 31 2E 30
2E 30 2E 30 00 00 ) // ...1.0.0.0..
.custom instance void
[mscorlib]System.Runtime.Versioning.TargetFrameworkAttribute::.ctor(string) = ( 01 00 1C 2E 4E
45 54 46 72 61 6D 65 77 6F 72 6B // ....NETFramework
2C 56 65 72 73 69 6F 6E 3D 76 34 2E 35 2E 32 01 // ,Version=v4.5.2.
https://riptutorial.com/es/home 60
00 54 0E 14 46 72 61 6D 65 77 6F 72 6B 44 69 73 // .T..FrameworkDis
70 6C 61 79 4E 61 6D 65 14 2E 4E 45 54 20 46 72 // playName..NET Fr
61 6D 65 77 6F 72 6B 20 34 2E 35 2E 32 ) // amework 4.5.2
.hash algorithm 0x00008004
.ver 1:0:0:0
}
.module HelloWorld.exe
// MVID: {2A7E1D59-1272-4B47-85F6-D7E1ED057831}
.imagebase 0x00400000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003 // WINDOWS_CUI
.corflags 0x00020003 // ILONLY 32BITPREFERRED
// Image base: 0x0000021C70230000
https://riptutorial.com/es/home 61
Capítulo 17: Contextos de sincronización
Observaciones
Un Contexto de Sincronización es una abstracción que permite consumir código para pasar
unidades de trabajo a un programador, sin necesidad de conocer cómo se programará el trabajo.
Examples
Ejecutar código en el hilo de la interfaz de usuario después de realizar un
trabajo en segundo plano
En este ejemplo, si intentara actualizar directamente MyTextBox.Text dentro del bucle for ,
obtendría un error de subprocesamiento. Al publicar la acción UpdateCallback en
SynchronizationContext , el cuadro de texto se actualiza en el mismo hilo que el resto de la interfaz
de usuario.
https://riptutorial.com/es/home 62
En la práctica, las actualizaciones de progreso deben realizarse utilizando una instancia de
System.IProgress<T> . La implementación predeterminada System.Progress<T> captura
automáticamente el contexto de sincronización en el que se crea.
https://riptutorial.com/es/home 63
Capítulo 18: Contratos de código
Observaciones
Los contratos de código permiten la compilación o el análisis en tiempo de ejecución de las
condiciones pre / post de los métodos y las condiciones invariables para los objetos. Estas
condiciones se pueden usar para garantizar que las personas que llaman y el valor de retorno
coincidan con los estados válidos para el procesamiento de la aplicación. Otros usos de los
contratos de código incluyen la generación de documentación.
Examples
Precondiciones
Las condiciones previas permiten que los métodos proporcionen valores mínimos requeridos para
los parámetros de entrada
Ejemplo...
//do work
}
Postcondiciones
Las condiciones posteriores aseguran que los resultados devueltos de un método coincidirán con
la definición proporcionada. Esto proporciona a la persona que llama una definición del resultado
esperado. Las condiciones posteriores pueden permitir implementaciones simplificadas, ya que el
analizador estático puede proporcionar algunos resultados posibles.
Ejemplo...
string GetValue()
{
Contract.Ensures(Contract.Result<string>() != null);
return null;
}
https://riptutorial.com/es/home 64
Analisis Estático Resultado ...
Usando Contratos de Código es posible aplicar un contrato a una interfaz. Esto se hace
declarando una clase abstracta que implementa las interfaces. La interfaz debe estar etiquetada
con el ContractClassAttribute y la definición del contrato (la clase abstracta) debe estar etiquetada
con el ContractClassForAttribute
C # Ejemplo ...
[ContractClass(typeof(MyInterfaceContract))]
public interface IMyInterface
{
string DoWork(string input);
}
//Never inherit from this contract defintion class
[ContractClassFor(typeof(IMyInterface))]
internal abstract class MyInterfaceContract : IMyInterface
{
private MyInterfaceContract() { }
Mientras que System.Diagnostics.Contracts está incluido dentro de .Net Framework. Para utilizar
https://riptutorial.com/es/home 65
los contratos de código, debe instalar las extensiones de Visual Studio.
En Extensions and Updates busque Code Contracts luego instale las Code Contracts Tools
Después de instalar las herramientas, debe habilitar los Code Contracts dentro de su solución de
Proyecto. Como mínimo, es probable que desee habilitar la Static Checking (comprobación
después de la compilación). Si está implementando una biblioteca que será utilizada por otras
soluciones, puede considerar también habilitar la Runtime Checking .
https://riptutorial.com/es/home 66
Lea Contratos de código en línea: https://riptutorial.com/es/dot-net/topic/1937/contratos-de-codigo
https://riptutorial.com/es/home 67
Capítulo 19: Descripción general de la API de
la biblioteca paralela de tareas (TPL)
Observaciones
La biblioteca paralela de tareas es un conjunto de tipos públicos y API que simplifican
drásticamente el proceso de agregar paralelismo y concurrencia a una aplicación. .Red. TPL se
introdujo en .Net 4 y es la forma recomendada de escribir código de subprocesos múltiples y
paralelo.
Examples
Realice el trabajo en respuesta a un clic del botón y actualice la interfaz de
usuario
Este ejemplo demuestra cómo puede responder a un clic de botón realizando algún trabajo en un
subproceso de trabajo y luego actualizar la interfaz de usuario para indicar que se ha completado.
https://riptutorial.com/es/home 68
Capítulo 20: Diagnostico del sistema
Examples
Cronógrafo
Este ejemplo muestra cómo se puede usar el Stopwatch para evaluar un bloque de código.
using System;
using System.Diagnostics;
public Benchmark()
{
sw = Stopwatch.StartNew();
}
https://riptutorial.com/es/home 69
Enviar comando a CMD y recibir salida
Este método permite enviar un command a Cmd.exe y devuelve la salida estándar (incluido el error
estándar) como una cadena:
p.Start();
Uso
Salida
https://riptutorial.com/es/home 70
{
var cmdOut = string.Empty;
Verb = "runas",
Domain = "doman1.co.za",
UserName = "administrator",
Password = GetPassword()
};
p.Start();
Obteniendo la contraseña:
return ss;
}
Notas
Los dos métodos anteriores devolverán una concatenación de STDOUT y STDERR, ya que
OutputDataReceived y ErrorDataReceived se ErrorDataReceived a la misma variable, cmdOut .
https://riptutorial.com/es/home 71
Capítulo 21: Encriptación / Criptografía
Observaciones
.NET Framework proporciona la implementación de muchos algoritmos criptográficos. Incluyen
básicamente algoritmos simétricos, algoritmos asimétricos y hashes.
Examples
RijndaelManaged
https://riptutorial.com/es/home 72
}
} finally {
aesAlg?.Clear();
}
return encrypt.ToArray();
}
Uso
Nota:
using System;
using System.IO;
using System.Security.Cryptography;
namespace Aes_Example
{
class AesExample
{
public static void Main()
{
try
{
string original = "Here is some data to encrypt!";
https://riptutorial.com/es/home 73
// Create a new instance of the Aes class.
// This generates a new key and initialization vector (IV).
using (Aes myAes = Aes.Create())
{
// Encrypt the string to an array of bytes.
byte[] encrypted = EncryptStringToBytes_Aes(original,
myAes.Key,
myAes.IV);
byte[] encrypted;
https://riptutorial.com/es/home 74
encrypted = msEncrypt.ToArray();
}
}
}
return plaintext;
}
}
}
Es una aplicación de demostración de consola, que muestra cómo cifrar una cadena utilizando el
cifrado AES estándar y cómo descifrarla después.
https://riptutorial.com/es/home 75
( AES = Advanced Encryption Standard , una especificación para el cifrado de datos
electrónicos establecida por el Instituto Nacional de Estándares y Tecnología (NIST) de EE. UU.
En 2001, que sigue siendo el estándar de facto para el cifrado simétrico)
Notas:
• En un escenario de cifrado real, debe elegir un modo de cifrado adecuado (se puede
asignar a la propiedad Mode seleccionando un valor de la enumeración CipherMode ). Nunca
use el CipherMode.ECB (modo de libro de códigos electrónico), ya que esto produce un flujo de
cifrado débil
• Para crear una Key buena (y no débil), use un generador criptográfico aleatorio o use el
ejemplo anterior ( Crear una clave a partir de una contraseña ). El tamaño de clave
recomendado es de 256 bits. Los tamaños de clave admitidos están disponibles a través de
la propiedad LegalKeySizes .
• Para inicializar el vector de inicialización IV , puede usar una SALT como se muestra en el
ejemplo anterior ( SAL aleatoria )
using System;
using System.Security.Cryptography;
using System.Text;
try
{
Console.WriteLine("Creating a key with PasswordDeriveBytes...");
https://riptutorial.com/es/home 76
tdes.Key = pdb.CryptDeriveKey("TripleDES", "SHA1", 192, tdes.IV);
Console.WriteLine("Operation complete.");
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
finally
{
// Clear the buffers
ClearBytes(pwd);
ClearBytes(salt);
Console.ReadLine();
}
/// <summary>
/// Generates a random salt value of the specified length.
/// </summary>
public static byte[] CreateRandomSalt(int length)
{
// Create a buffer
byte[] randBytes;
if (length >= 1)
{
randBytes = new byte[length];
}
else
{
randBytes = new byte[1];
}
/// <summary>
/// Clear the bytes in a buffer so they can't later be read from memory.
/// </summary>
public static void ClearBytes(byte[] buffer)
{
// Check arguments.
if (buffer == null)
{
throw new ArgumentNullException("buffer");
}
https://riptutorial.com/es/home 77
// Set each byte in the buffer to 0.
for (int x = 0; x < buffer.Length; x++)
{
buffer[x] = 0;
}
}
#endregion
}
Es una demostración de la consola, y muestra cómo crear una clave segura basada en una
contraseña definida por el usuario, y cómo crear una SALT aleatoria basada en el generador
criptográfico aleatorio.
Notas:
• Por lo general, este mecanismo se usa para proteger una clave generada aleatoriamente
más fuerte mediante una contraseña, que cifra una gran cantidad de datos. También puede
usarlo para proporcionar múltiples contraseñas de diferentes usuarios para dar acceso a los
mismos datos (está protegido por una clave aleatoria diferente).
Codigo de desencriptacion
https://riptutorial.com/es/home 78
byte[] cipherBytes = Convert.FromBase64String(cipherText);
using (Aes encryptor = Aes.Create())
{
Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(CryptKey, new byte[] { 0x49, 0x76,
0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
encryptor.Key = pdb.GetBytes(32);
encryptor.IV = pdb.GetBytes(16);
cipherText = Encoding.Unicode.GetString(ms.ToArray());
}
}
return cipherText;
}
Codigo de cifrado
cipherText = Convert.ToBase64String(ms.ToArray());
}
}
return cipherText;
}
Uso
https://riptutorial.com/es/home 79
var decrypted = Decrypt(encrypted);
https://riptutorial.com/es/home 80
Capítulo 22: Enhebrado
Examples
Accediendo a los controles de formulario desde otros hilos.
Si desea cambiar un atributo de un control, como un cuadro de texto o una etiqueta de otro hilo
que no sea el hilo de la GUI que creó el control, deberá invocarlo o, de lo contrario, podría
aparecer un mensaje de error que indique:
En cambio, cuando desea cambiar el texto de un cuadro de texto dentro de un hilo que no lo
posee, use Control.Invoke o Control.BeginInvoke. También puede usar Control.InvokeRequired
para verificar si es necesario invocar el control.
Si necesita hacer esto a menudo, puede escribir una extensión para objetos invocables para
reducir la cantidad de código necesario para realizar esta comprobación:
https://riptutorial.com/es/home 81
}
Y actualizar el cuadro de texto desde cualquier hilo se vuelve un poco más simple:
Tenga en cuenta que Control.BeginInvoke como se usa en este ejemplo es asíncrono, lo que
significa que el código que viene después de una llamada a Control.BeginInvoke se puede
ejecutar inmediatamente después, ya sea que el delegado pasado se haya ejecutado o no.
https://riptutorial.com/es/home 82
Capítulo 23: Escribir y leer desde StdErr
stream
Examples
Escribir en la salida de error estándar utilizando la consola
};
process.ErrorDataReceived += (s, e) => errors.AppendLine(e.Data);
process.Start();
process.BeginErrorReadLine();
process.WaitForExit();
https://riptutorial.com/es/home 83
Capítulo 24: Examen de la unidad
Examples
Agregar el proyecto de prueba de unidad MSTest a una solución existente
MSTest (el marco de prueba predeterminado) requiere que sus clases de prueba [TestClass]
decoradas por un atributo [TestClass] y los métodos de prueba con un atributo [TestMethod] , y
que sea pública.
[TestClass]
public class FizzBuzzFixture
{
[TestMethod]
public void Test1()
{
//arrange
var solver = new FizzBuzzSolver();
//act
var result = solver.FizzBuzz(1);
//assert
Assert.AreEqual("1",result);
}
}
https://riptutorial.com/es/home 84
Capítulo 25: Excepciones
Observaciones
Relacionado:
Examples
Atrapando una excepción
La persona que llama puede manejar estas excepciones "atrapándolas", y solo debe hacerlo
cuando:
Se debe tener en cuenta que elegir no capturar una excepción es perfectamente válido si la
intención es que se maneje en un nivel superior.
Stream fileStream;
try
{
fileStream = File.Open(filename);
}
catch (FileNotFoundException)
https://riptutorial.com/es/home 85
{
Console.WriteLine("File '{0}' could not be found.", filename);
}
Puede utilizarse para liberar o limpiar los recursos adquiridos en el bloque try { ... } forma
segura.
try
{
fileStream = File.Open(filename);
}
catch (FileNotFoundException)
{
Console.WriteLine("File '{0}' could not be found.", filename);
}
finally
{
if (fileStream != null)
{
fileStream.Dispose();
}
}
Cuando desea capturar una excepción y hacer algo, pero no puede continuar la ejecución del
bloque de código actual debido a la excepción, es posible que desee volver a emitir la excepción
al siguiente controlador de excepciones en la pila de llamadas. Hay buenas y malas maneras de
hacer esto.
https://riptutorial.com/es/home 86
// we do not need a reference to the exception
Console.WriteLine("Dividing by zero would destroy the universe.");
// remember that the stack trace of the outer Exception will point to the
// next line
// you'll need to examine the InnerException property to get the stack trace
// to the line that actually started the problem
Puede filtrar por tipo de excepción e incluso por propiedades de excepción (nuevo en C # 6.0, un
poco más disponible en VB.NET (citación necesaria)):
Filtros de excepción
Dado que las excepciones de C # 6.0 se pueden filtrar usando el operador when .
Esto es similar a usar un simple if pero no desenrolla la pila si no se cumple la condición dentro
de when .
Ejemplo
https://riptutorial.com/es/home 87
try
{
// ...
}
catch (Exception e) when (e.InnerException != null) // Any condition can go in here.
{
// ...
}
Dentro de un bloque catch , la palabra clave throw se puede usar sola, sin especificar un valor de
excepción, para volver a emitir la excepción que se acaba de capturar. La repetición de una
excepción permite que la excepción original continúe en la cadena de manejo de excepciones,
preservando su pila de llamadas o datos asociados:
try {...}
catch (Exception ex) {
// Note: the ex variable is *not* used
throw;
}
Un antipatrón común es throw ex , que tiene el efecto de limitar la siguiente vista del controlador
de excepción de la traza de pila:
try {...}
catch (Exception ex) {
// Note: the ex variable is thrown
// future stack traces of the exception will not see prior calls
throw ex;
}
Ocasionalmente, querría atrapar una excepción y lanzarla desde un hilo o método diferente
mientras se conserva la pila de excepciones original. Esto se puede hacer con
ExceptionDispatchInfo :
using System.Runtime.ExceptionServices;
void Main()
{
https://riptutorial.com/es/home 88
ExceptionDispatchInfo capturedException = null;
try
{
throw new Exception();
}
catch (Exception ex)
{
capturedException = ExceptionDispatchInfo.Capture(ex);
}
Foo(capturedException);
}
if (capturedException != null)
{
// Exception stack trace will show it was thrown from Main() and not from Foo()
exceptionDispatchInfo.Throw();
}
}
https://riptutorial.com/es/home 89
Capítulo 26: Expresiones regulares
(System.Text.RegularExpressions)
Examples
Compruebe si el patrón coincide con la entrada
// true
return Regex.IsMatch(input, pattern);
}
Opciones de paso
// true
return Regex.IsMatch(input, pattern, RegexOptions.IgnoreCase | RegexOptions.Singleline);
}
Partido en grupos
// World
return match.Groups["Subject"].Value;
https://riptutorial.com/es/home 90
}
Utilizando
using System.Text.RegularExpressions;
Código
static void Main(string[] args)
{
string input = "Carrot Banana Apple Cherry Clementine Grape";
// Find words that start with uppercase 'C'
string pattern = @"\bC\w*\b";
Salida
Carrot
Cherry
Clementine
https://riptutorial.com/es/home 91
Capítulo 27: Flujo de datos TPL
Observaciones
System.Threading.Tasks
System.Net.Http
System.Net
Post intentará agregar el elemento de forma sincrónica y devolverá un bool que bool si tuvo éxito o
no. Puede que no tenga éxito cuando, por ejemplo, un bloque ha alcanzado su BoundedCapcity y
no tiene aún más espacio para nuevos elementos. SendAsync por otro lado, devolverá una
Task<bool> incompleta que puede await . Esa tarea se completará en el futuro con un resultado
true cuando el bloque borre su cola interna y pueda aceptar más elementos o con un resultado
false si se está reduciendo permanentemente (por ejemplo, como resultado de la cancelación).
Examples
Publicar en un ActionBlock y esperar a que se complete
block.Complete(); // Tell the block to complete and stop accepting new items
await block.Completion; // Asynchronously wait until all items completed processingu
https://riptutorial.com/es/home 92
// Create a block the accepts a uri and returns its contents as a string
var downloaderBlock = new TransformBlock<string, string>(
async uri => await httpClient.GetStringAsync(uri));
// Create a block that accepts the content and prints it to the console
var printerBlock = new ActionBlock<string>(
contents => Console.WriteLine(contents));
// Post urls to the first block which will pass their contents to the second one.
downloaderBlock.Post("http://youtube.com");
downloaderBlock.Post("http://github.com");
downloaderBlock.Post("http://twitter.com");
class Program
{
private static BufferBlock<double> buffer = new BufferBlock<double>();
static void Main (string[] args)
{
//start a task that will every 1 second post a value from the producer to buffer block
var producerTask = Task.Run(async () =>
{
var producer = new Producer();
while(true)
{
buffer.Post(producer.Produce());
await Task.Delay(1000);
}
});
//start a task that will recieve values from bufferblock and consume it
var consumerTask = Task.Run(() =>
https://riptutorial.com/es/home 93
{
var consumer = new Consumer();
while(true)
{
consumer.Consume(buffer.Receive());
}
});
while (!cancellationToken.IsCancellationRequested)
{
var value = random.Next();
await bufferBlock.SendAsync(value, cancellationToken);
}
});
https://riptutorial.com/es/home 94
Capítulo 28: Formas VB
Examples
Hola Mundo en Formas VB.NET
Load () se llamará primero, y solo una vez, cuando se carga el formulario por primera vez. Se
llamará a Show () cada vez que el usuario inicie el formulario. Activate () se llamará cada vez que
el usuario active el formulario.
Load () se ejecutará antes de llamar a Show (), pero tenga cuidado: llamar a msgBox () en show
puede hacer que se ejecute msgBox () antes de que finalice Load (). En general, es una mala
idea depender del orden de los eventos entre Load (), Show () y similares.
Para principiantes
Algunas cosas que todos los principiantes deben saber / hacer que les ayudarán a tener un buen
comienzo con VB .Net:
End Class
Utilice &, no + para la concatenación de cadenas. Las cuerdas deben estudiarse con cierto detalle
ya que son ampliamente utilizadas.
https://riptutorial.com/es/home 95
Nunca utilice Application.DoEvents . Preste atención a la 'Precaución'. Cuando llegue a un punto
en el que esto parezca algo que debe usar, pregunte.
La documentación es tu amiga.
Temporizador de formularios
Por ejemplo, podría utilizarse para mostrar al usuario la hora del día periódicamente.
Pero este temporizador no es adecuado para la temporización. Un ejemplo lo estaría usando para
una cuenta atrás. En este ejemplo simularemos una cuenta regresiva a tres minutos. Este puede
muy bien ser uno de los ejemplos más aburridos importantes aquí.
https://riptutorial.com/es/home 96
Dim stpw As New Stopwatch
Dim ctSecs As Integer
Después de hacer clic en el botón 1, pasan aproximadamente tres minutos y label1 muestra los
resultados. ¿Label1 muestra 180? Probablemente no. ¡En mi máquina mostraba 182.5!
https://riptutorial.com/es/home 97
Hay otros temporizadores que pueden usarse según sea necesario. Esta búsqueda debería
ayudar en ese sentido.
https://riptutorial.com/es/home 98
Capítulo 29: Gestión de la memoria
Observaciones
Las aplicaciones críticas para el rendimiento en aplicaciones administradas .NET pueden verse
gravemente afectadas por el GC. Cuando se ejecuta el GC, todos los demás subprocesos se
suspenden hasta que se completa. Por esta razón, se recomienda evaluar cuidadosamente los
procesos de GC y determinar cómo minimizar cuando se ejecuta.
Examples
Recursos no gestionados
StreamReader sr;
string textFromFile;
string filename = "SomeFile.txt";
try
{
sr = new StreamReader(filename);
textFromFile = sr.ReadToEnd();
}
finally
{
if (sr != null) sr.Dispose();
}
string textFromFile;
string filename = "SomeFile.txt";
https://riptutorial.com/es/home 99
using (StreamReader sr = new Streamreader(filename))
{
textFromFile = sr.ReadToEnd();
}
using System.Runtime.InteropServices;
https://riptutorial.com/es/home 100
Capítulo 30: Globalización en ASP.NET MVC
utilizando la internacionalización inteligente
para ASP.NET
Observaciones
Inteligente internacionalización para la página ASP.NET
El beneficio de este enfoque es que no tiene que saturar los controladores y otras clases con
código para buscar valores de archivos .resx. Simplemente rodee el texto entre [[[corchetes
triples.]]] (El delimitador es configurable.) Un HttpModule busca una traducción en su archivo .po
para reemplazar el texto delimitado. Si se encuentra una traducción, HttpModule sustituye a la
traducción. Si no se encuentra ninguna traducción, elimina los corchetes triples y renderiza la
página con el texto original sin traducir.
Los archivos .po son un formato estándar para suministrar traducciones para aplicaciones, por lo
que hay una serie de aplicaciones disponibles para editarlas. Es fácil enviar un archivo .po a un
usuario no técnico para que puedan agregar traducciones.
Examples
Configuración básica y configuración
3. Agregue una carpeta llamada "locale" a la raíz de su sitio. Cree una subcarpeta para cada
cultura que desee apoyar. Por ejemplo, /locale/fr/ .
4. En cada carpeta específica de cada cultura, cree un archivo de texto llamado messages.po .
5. Para propósitos de prueba, ingrese las siguientes líneas de texto en su archivo messages.po :
#: Translation test
msgid "Hello, world!"
https://riptutorial.com/es/home 101
msgstr "Bonjour le monde!"
using System.Web.Mvc;
namespace I18nDemo.Controllers
{
public class DefaultController : Controller
{
public ActionResult Index()
{
// Text inside [[[triple brackets]]] must precisely match
// the msgid in your .po file.
return Content("[[[Hello, world!]]]");
}
}
}
https://riptutorial.com/es/home 102
Capítulo 31: Instrumentos de cuerda
Observaciones
En las cadenas .NET System.String son secuencias de caracteres System.Char , cada carácter es
una unidad de código codificada en UTF-16. Esta distinción es importante porque la definición de
caracteres en el lenguaje hablado y la definición de caracteres en .NET (y en muchos otros
idiomas) son diferentes.
Un carácter , que debería llamarse correctamente grafema , se muestra como un glifo y está
definido por uno o más puntos de código Unicode. Cada punto de código se codifica en una
secuencia de unidades de código . Ahora debería estar claro por qué un solo System.Char no
siempre representa un grafema, veamos en el mundo real cómo son diferentes:
• Un grafema, debido a la combinación de caracteres , puede dar lugar a dos o más puntos
de código: à está compuesto por dos puntos de código: U + 0061 LETRA PEQUEÑA LETRA
A y U + 0300 COMBINACIÓN DEL ACUMENTO GRAVE . Este es el error más común
porque "à".Length == 2 mientras que usted puede esperar 1 .
• Hay caracteres duplicados, por ejemplo à puede ser un único punto de código U + 00E0
LETRA A LATINA PEQUEÑA CON GRAVE o dos puntos de código como se explicó
anteriormente. Obviamente, deben comparar lo mismo: "\u00e0" == "\u0061\u0300" (incluso
si "\u00e0".Length != "\u0061\u0300".Length ). Esto es posible debido a la normalización de la
cadena realizada por el método String.Normalize() .
• Una secuencia Unicode puede contener una secuencia compuesta o descompuesta, por
ejemplo, el carácter U + D55C HAN CHARACTER puede ser un único punto de código
(codificado como una sola unidad de código en UTF-16) o una secuencia descompuesta de
sus sílabas , y . Deben ser comparados iguales.
• Un punto de código puede codificarse en más de una unidad de código: el carácter U +
2008A HAN CHARACTER se codifica como dos System.Char ( "\ud840\udc8a" ) incluso si es
solo un punto de código: UTF-16 La codificación no es de tamaño fijo! Esta es una fuente de
innumerables errores (también errores graves de seguridad), si, por ejemplo, su aplicación
aplica una longitud máxima y trunca ciegamente la cadena, entonces puede crear una
cadena no válida.
• Algunos idiomas tienen digraph y trigraphs, por ejemplo, en ch ch ch es una letra
independiente (después de h y antes de i , cuando ordene una lista de cadenas, tendrá
fyzika antes de chemie .
Hay muchos más problemas relacionados con el manejo del texto. Consulte, por ejemplo, ¿Cómo
puedo realizar una comparación de caracteres por caracteres en Unicode? para una introducción
más amplia y más enlaces a argumentos relacionados.
En general, cuando se trata de texto internacional , puede usar esta función simple para enumerar
elementos de texto en una cadena (evitando romper los sustitutos y la codificación de Unicode):
https://riptutorial.com/es/home 103
public static IEnumerable<string> EnumerateCharacters(this string s)
{
if (s == null)
return Enumerable.Empty<string>();
Examples
Contar personajes distintos
Si necesita contar caracteres distintos, entonces, por las razones explicadas en la sección
Comentarios , no puede simplemente usar la propiedad Length porque es la longitud de la matriz
de System.Char que no son caracteres sino unidades de código (no puntos de código Unicode). ni
grafemas). Si, por ejemplo, simplemente escribe text.Distinct().Count() obtendrá resultados
incorrectos, código correcto:
Contar personajes
Si necesita contar caracteres , entonces, por las razones explicadas en la sección Comentarios ,
no puede simplemente usar la propiedad Longitud porque es la longitud de la matriz de
System.Char que no son caracteres sino unidades de código (no son puntos de código Unicode ni
grafemas). El código correcto es entonces:
int count = 0;
https://riptutorial.com/es/home 104
var enumerator = StringInfo.GetTextElementEnumerator(text);
while (enumerator.MoveNext())
++count;
return count;
}
}
Tenga en cuenta que la comparación de cadenas (en contraste con la comparación de caracteres
que es invariante de la cultura) siempre debe realizarse de acuerdo con las reglas de una cultura
específica.
No podemos dividir una cadena en puntos arbitrarios (porque un System.Char puede no ser válido
solo porque es un carácter de combinación o parte de un sustituto), entonces el código debe tener
eso en cuenta (tenga en cuenta que con la longitud me refiero al número de grafemas, no al
número de unidades de código ):
if (!enumerator.MoveNext())
yield break;
}
}
https://riptutorial.com/es/home 105
Convertir cadena a / desde otra codificación
Las cadenas .NET contienen System.Char (unidades de código UTF-16). Si desea guardar (o
administrar) texto con otra codificación, debe trabajar con una matriz de System.Byte .
Debido a que el codificador / decodificador generalmente funciona muy cerca uno del otro, se
agrupan en una clase derivada de System.Text.Encoding , las clases derivadas ofrecen
conversiones a / desde codificaciones populares (UTF-8, UTF-16 y así sucesivamente).
Ejemplos:
Convertir una cadena a UTF-8
byte[] data = Encoding.UTF8.GetBytes("This is my text");
Todo en .NET es un objeto, por lo tanto, cada tipo tiene el método ToString() definido en la clase
Object que puede ser anulado. La implementación predeterminada de este método solo devuelve
el nombre del tipo:
https://riptutorial.com/es/home 106
Console.WriteLine(foo); // outputs Foo
Las cuerdas son inmutables. Simplemente no puedes cambiar la cadena existente. Cualquier
operación en la cadena crea una nueva instancia de la cadena con un nuevo valor. Esto significa
que si necesita reemplazar un solo carácter en una cadena muy larga, la memoria se asignará
para un nuevo valor.
Si necesita realizar muchas operaciones con valor de cadena, use la clase StringBuilder que está
diseñada para la manipulación eficiente de cadenas:
Cuerdas
https://riptutorial.com/es/home 107
A pesar de que String es un tipo de referencia, el operador == compara los valores de cadena en
lugar de las referencias.
Como sabrás, la string es solo una matriz de caracteres. Pero si crees que la verificación y
comparación de la igualdad de las cadenas se hace carácter por carácter, estás equivocado. Esta
operación es específica de la cultura (ver Comentarios más abajo): algunas secuencias de
caracteres pueden tratarse como iguales dependiendo de la cultura .
Use sobrecargas del método String.Equals que acepte el valor de enumeración StringComparison
adicional, si necesita cambiar el comportamiento predeterminado.
https://riptutorial.com/es/home 108
Capítulo 32: Invocación de plataforma
Sintaxis
• [DllImport ("Example.dll")] static extern void SetText (string inString);
• [DllImport ("Example.dll")] static extern void GetText (StringBuilder outString);
• Texto de cadena [MarshalAs (UnmanagedType.ByValTStr, SizeConst = 32)];
• [MarshalAs (UnmanagedType.ByValArray, SizeConst = 128)] byte [] byteArr;
• [StructLayout (LayoutKind.Sequential)] public struct PERSON {...}
• [StructLayout (LayoutKind.Explicit)] public struct MarshaledUnion {[FieldOffset (0)] ...}
Examples
Llamando a una función dll Win32
using System.Runtime.InteropServices;
class PInvokeExample
{
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern uint MessageBox(IntPtr hWnd, String text, String caption, int
options);
Declare una función como static extern stting DllImportAttribute con su propiedad Value
establecida en .dll nombre. No olvide utilizar el System.Runtime.InteropServices nombres
System.Runtime.InteropServices . Entonces llámalo como un método estático regular.
Utilice pinvoke.net .
Antes de declarar una función API extern Windows en su código, considere buscarla en
pinvoke.net . Lo más probable es que ya tengan una declaración adecuada con todos los tipos de
soporte y buenos ejemplos.
Arreglando matrices
https://riptutorial.com/es/home 109
Arreglos de tipo simple.
[DllImport("Example.dll")]
static extern void SetArray(
[MarshalAs(UnmanagedType.LPArray, SizeConst = 128)]
byte[] data);
Matrices de cuerda
[DllImport("Example.dll")]
static extern void SetStrArray(string[] textLines);
Estructuras de cálculo
Estructura simple
Firma C ++:
Definición de C #
Firma C ++
typedef struct
{
int length;
int *data;
} VECTOR;
https://riptutorial.com/es/home 110
La matriz de data debe definirse como IntPtr y la memoria debe asignarse explícitamente con
Marshal.AllocHGlobal() (y liberarse con las Marshal.FreeHGlobal() palabras Marshal.FreeHGlobal() ):
[StructLayout(LayoutKind.Sequential)]
public struct VECTOR : IDisposable
{
int length;
IntPtr dataBuf;
[DllImport("vectors.dll")]
public static extern void SetVector([In]ref VECTOR vector);
Firma C ++:
typedef struct
{
char *name;
} USER;
Cuando dichos datos pasan de código no administrado y la memoria es asignada por las
funciones no administradas, el llamante administrado debe recibirla en una variable IntPrt y
convertir el búfer en una matriz administrada. En el caso de cadenas, hay un método
Marshal.PtrToStringAnsi() conveniente:
[StructLayout(LayoutKind.Sequential)]
https://riptutorial.com/es/home 111
public struct USER
{
IntPtr nameBuffer;
public string name { get { return Marshal.PtrToStringAnsi(nameBuffer); } }
}
[DllImport("users.dll")]
public static extern bool GetCurrentUser(out USER user);
Declaración de C ++
typedef union
{
char c;
int i;
} CharOrInt;
Declaración de C #
[StructLayout(LayoutKind.Explicit)]
public struct CharOrInt
{
[FieldOffset(0)]
public byte c;
[FieldOffset(0)]
public int i;
}
La superposición de un valor de referencia con un tipo de valor uno no está permitida, por lo que
no puede simplemente usar el FieldOffset(0) text; FieldOffset(0) i; no compilará para
typedef union
{
char text[128];
int i;
} TextOrInt;
[StructLayout(LayoutKind.Sequential)]
public struct TextOrInt
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)]
public byte[] text;
public int i { get { return BitConverter.ToInt32(text, 0); } }
}
https://riptutorial.com/es/home 112
Lea Invocación de plataforma en línea: https://riptutorial.com/es/dot-net/topic/1643/invocacion-de-
plataforma
https://riptutorial.com/es/home 113
Capítulo 33: Inyección de dependencia
Observaciones
Problemas resueltos por inyección de dependencia
Si no utilizáramos la inyección de dependencia, la clase Greeter podría verse más como esto:
Es un "control freak" porque controla la creación de la clase que proporciona el saludo, controla
de dónde proviene la cadena de conexión SQL y controla la salida.
La inyección de dependencia nos ayuda a lograr esa inversión de dependencia porque lleva a
escribir clases que dependen de abstracciones. La clase Greeter "no sabe" nada en absoluto
sobre los detalles de implementación de IGreetingProvider e IGreetingWriter . Solo se sabe que
las dependencias inyectadas implementan esas interfaces. Eso significa que los cambios en las
clases concretas que implementan IGreetingProvider e IGreetingWriter no afectarán a Greeter .
Tampoco los reemplazará con implementaciones completamente diferentes. Solo los cambios en
las interfaces lo harán. Greeter está desacoplado.
Greeteres fácil de realizar una prueba unitaria porque podemos inyectar implementaciones
simuladas de sus dependencias que son más fáciles de ejecutar y verificar que llamar a un
procedimiento almacenado o leer la salida de la consola. No requiere una cadena de conexión en
app.config.
https://riptutorial.com/es/home 114
Las implementaciones concretas de IGreetingProvider y IGreetingWriter pueden ser más
complejas. Ellos, a su vez, pueden tener sus propias dependencias que se inyectan en ellos. (Por
ejemplo, inyectaríamos la cadena de conexión SQL en SqlGreetingProvider ). Pero esa
complejidad está "oculta" de otras clases que solo dependen de las interfaces. Eso hace que sea
más fácil modificar una clase sin un "efecto dominó" que requiere que realicemos los cambios
correspondientes a otras clases.
Examples
Inyección de dependencia - Ejemplo simple
Esta clase se llama Greeter . Su responsabilidad es dar un saludo. Tiene dos dependencias .
Necesita algo que le dé el saludo de salida, y luego necesita una forma de emitir ese saludo. Esas
dependencias se describen como interfaces, IGreetingProvider e IGreetingWriter . En este
ejemplo, esas dos dependencias se "inyectan" en Greeter . (Explicación adicional siguiendo el
ejemplo).
https://riptutorial.com/es/home 115
Algunas convenciones comunes:
• El constructor guarda las dependencias como campos private . Tan pronto como se crea
una instancia de la clase, esas dependencias están disponibles para todos los otros
métodos no estáticos de la clase.
• Los campos private son de readonly . Una vez que se establecen en el constructor, no se
pueden cambiar. Esto indica que esos campos no deben (y no pueden) ser modificados
fuera del constructor. Eso asegura aún más que esas dependencias estarán disponibles
durante toda la vida de la clase.
• Las dependencias son interfaces. Esto no es estrictamente necesario, pero es común
porque facilita la sustitución de una implementación de la dependencia por otra. También
permite proporcionar una versión simulada de la interfaz para propósitos de prueba unitaria.
Cómo la inyección de dependencia hace que las pruebas unitarias sean más
fáciles
Esto se basa en el ejemplo anterior de la clase Greeter que tiene dos dependencias,
IGreetingProvider e IGreetingWriter .
[TestClass]
public class GreeterTests
{
[TestMethod]
public void Greeter_WritesGreeting()
{
var greetingProvider = new TestGreetingProvider();
var greetingWriter = new TestGreetingWriter();
var greeter = new Greeter(greetingProvider, greetingWriter);
https://riptutorial.com/es/home 116
greeter.Greet();
Assert.AreEqual(greetingWriter[0], TestGreetingProvider.TestGreeting);
}
}
Inyección de dependencia significa clases de escritura para que no controlen sus dependencias;
en cambio, se les proporcionan sus dependencias ("inyectadas").
Cada clase individual está bien escrita y es fácil de evaluar. Pero ahora hay un problema
diferente: crear una instancia de una clase se ha vuelto mucho más complicado. Supongamos
que estamos creando una instancia de una clase CustomerService . Tiene dependencias y sus
dependencias tienen dependencias. Construir una instancia puede verse algo como esto:
https://riptutorial.com/es/home 117
}
Podría preguntarse, ¿por qué no poner toda la construcción gigante en una función separada que
simplemente devuelve CustomerService ? Una razón es que debido a que las dependencias para
cada clase se inyectan en ella, una clase no es responsable de saber si esas dependencias son
IDisposable o desecharlas. Simplemente los usa. Entonces, si tuviéramos una función
GetCustomerService() que devolviera un CustomerService completamente construido, esa clase
podría contener una cantidad de recursos desechables y ninguna forma de acceder o
desecharlos.
Y aparte de desechar IDisposable , ¿quién quiere llamar a una serie de constructores anidados
como ese, alguna vez? Ese es un pequeño ejemplo. Podría ser mucho, mucho peor.
Nuevamente, eso no significa que escribimos las clases de manera incorrecta. Las clases pueden
ser individualmente perfectas. El reto es componerlos juntos.
Un contenedor de inyección de dependencia simplifica eso. Nos permite especificar qué clase o
valor debe usarse para cumplir con cada dependencia. Este ejemplo ligeramente simplificado
utiliza Castle Windsor:
• Si una clase requiere ILogWriter , cree una instancia de LogWriter . LogWriter requiere una
ruta de archivo. Utilice este valor de AppSettings .
• Si una clase requiere IAuthorizationRepository , cree una instancia de
SqlAuthorizationRepository . Requiere una cadena de conexión. Utilice este valor de la
sección ConnectionStrings .
• Si una clase requiere ICustomerDataProvider , cree un CustomerApiClient y proporcione la
cadena que necesita desde AppSettings .
Cuando solicitamos una dependencia del contenedor, llamamos a eso "resolver" una
dependencia. Es una mala práctica hacer eso directamente usando el contenedor, pero esa es
una historia diferente. Para propósitos de demostración, ahora podríamos hacer esto:
https://riptutorial.com/es/home 118
El contenedor sabe que CustomerService depende de IAuthorizationRepository y
ICustomerDataProvider . Sabe qué clases necesita crear para cumplir con esos requisitos. Esas
clases, a su vez, tienen más dependencias, y el contenedor sabe cómo cumplirlas. Creará todas
las clases que necesite hasta que pueda devolver una instancia de CustomerService .
Si llega a un punto en el que una clase requiere una dependencia que no hemos registrado, como
IDoesSomethingElse , cuando intentemos resolver el servicio al CustomerService se producirá una
excepción clara que nos indica que no hemos registrado nada para cumplir con ese requisito.
Cada marco DI se comporta de manera un poco diferente, pero generalmente nos dan cierto
control sobre cómo se ejemplifican ciertas clases. Por ejemplo, ¿queremos que cree una instancia
de LogWriter y la proporcione a todas las clases que dependen de ILogWriter , o queremos que
cree una nueva cada vez? La mayoría de los contenedores tienen una manera de especificar eso.
¿Qué pasa con las clases que implementan IDisposable ? Por eso llamamos
container.Release(customerService); al final. La mayoría de los contenedores (incluyendo
Windsor), avanzará hacia atrás a través de todas las dependencias creadas y Dispose los que
necesitan de desecharlas. Si CustomerService es IDisposable también lo eliminará.
Registrar dependencias como se ve arriba puede parecer más código para escribir. Pero cuando
tenemos muchas clases con muchas dependencias, entonces realmente vale la pena. Y si
tuviéramos que escribir esas mismas clases sin usar la inyección de dependencia, entonces esa
misma aplicación con muchas clases sería difícil de mantener y probar.
Esto araña la superficie de por qué usamos contenedores de inyección de dependencia. La forma
en que configuramos nuestra aplicación para usar una (y usarla correctamente) no es solo un
tema, sino una serie de temas, ya que las instrucciones y los ejemplos varían de un contenedor a
otro.
https://riptutorial.com/es/home 119
Capítulo 34: JSON en .NET con
Newtonsoft.Json
Introducción
El paquete Newtonsoft.Json ha convertido en el estándar de facto para usar y manipular texto y
objetos con formato JSON en .NET. Es una herramienta robusta, rápida y fácil de usar.
Examples
Serializar objeto en JSON
using Newtonsoft.Json;
https://riptutorial.com/es/home 120
Capítulo 35: Leer y escribir archivos zip
Introducción
La clase ZipFile vive en el espacio de nombres System.IO.Compression . Se puede utilizar para
leer y escribir en archivos Zip.
Observaciones
• También puede utilizar un MemoryStream en lugar de un FileStream.
• Excepciones
Excepción Condición
Examples
Listado de contenidos ZIP
Este fragmento de código mostrará una lista de todos los nombres de archivos de un archivo zip.
Los nombres de archivo son relativos a la raíz zip.
https://riptutorial.com/es/home 121
}
}
Para actualizar un archivo ZIP, el archivo debe abrirse con ZipArchiveMode.Update en su lugar.
https://riptutorial.com/es/home 122
using(var writer = new StreamWriter(entry.Open()))
{
writer.WriteLine("Test line");
}
https://riptutorial.com/es/home 123
Capítulo 36: LINQ
Introducción
LINQ (Language Integrated Query) es una expresión que recupera datos de un origen de datos.
LINQ simplifica esta situación al ofrecer un modelo consistente para trabajar con datos a través
de varios tipos de fuentes de datos y formatos. En una consulta LINQ, siempre está trabajando
con objetos. Utiliza los mismos patrones de codificación básicos para consultar y transformar
datos en documentos XML, bases de datos SQL, conjuntos de datos ADO.NET, colecciones .NET
y cualquier otro formato para el que un proveedor esté disponible. LINQ se puede utilizar en C # y
VB.
Sintaxis
• agregación estática pública de TSource <TSource> (esta fuente IEnumerable <TSource>,
Func <TSource, TSource, TSource> func)
• agregación estática pública TAccumulate <TSource, TAccumulate> (esta fuente
IEnumerable <TSource>, TAccumulate seed, Func <TAccumulate, TSource, TAccumulate>
func)
• agregación estática pública de TResult <TSource, TAccumulate, TResult> (esta fuente
IEnumerable <TSource>, fuente de TAccumulate, Func <TAccumulate, TSource,
TAccumulate> func, Func <TAccumulate, TResult> resultadoSelector)
• Public static Boolean All <TSource> (este IEnumerable <TSource> source, Func <TSource,
Boolean> predicate)
• Public static Boolean Any <TSource> (esta fuente IEnumerable <TSource>)
• Public static Boolean Any <TSource> (este IEnumerable <TSource> source, Func
<TSource, Boolean> predicate)
• IEnumerable estático público <TSource> AsEnumerable <TSource> (esta fuente <TSource>
IEnumerable)
• Promedio Decimal estático público (esta fuente <Decimal> IEnumerable)
• Promedio doble estático público (esta fuente <Double> de IEnumerable)
• Promedio público doble estático (esta fuente IEnumerable <Int32>)
• Promedio público doble estático (esta fuente IEnumerable <Int64>)
• Promedio público nullable <Decimal> (este IEnumerable <Nullable <Decimal>> fuente)
• Nullable estático público <Double> Promedio (este IEnumerable <Nullable <Double>>
fuente)
• Nullable estático público <Double> Promedio (este IEnumerable <Nullable <Int32>> fuente)
• Nullable estático público <Double> Promedio (este IEnumerable <Nullable <Int64>> fuente)
• Nullable estático público <Single> Promedio (este IEnumerable <Nullable <Single>> fuente)
• Promedio único estático público (esta fuente <Single> de IEnumerable)
• Promedio Decimal estático público <TSource> (este IEnumerable <TSource> source, Func
<TSource, Decimal> selector)
• Promedio público doble estático <TSource> (esta fuente IEnumerable <TSource>, Func
<TSource, Double> selector)
https://riptutorial.com/es/home 124
• Promedio público doble estático <TSource> (este IEnumerable <TSource> fuente, Func
<TSource, Int32> selector)
• Promedio público doble estático <TSource> (este IEnumerable <TSource> fuente, Func
<TSource, Int64> selector)
• Nullable estático público <Decimal> Promedio <TSource> (este IEnumerable <TSource>
fuente, Func <TSource, Nullable <Decimal>> selector)
• Nullable estático público <Double> Promedio <TSource> (este IEnumerable <TSource>
fuente, Func <TSource, Nullable <Double>> selector)
• Nullable estático público <Double> Promedio <TSource> (este IEnumerable <TSource>
fuente, Func <TSource, Nullable <Int32>> selector)
• Nullable estático público <Double> Promedio <TSource> (este IEnumerable <TSource>
fuente, Func <TSource, Nullable <Int64>> selector)
• Nullable estático público <Single> Promedio <TSource> (este IEnumerable <TSource>
fuente, Func <TSource, Nullable <Single>> selector)
• Promedio único público estático <TSource> (este IEnumerable <TSource> fuente, Func
<TSource, Single> selector)
• Public static IEnumerable <TResult> Cast <TResult> (esta fuente IEnumerable)
• pública <Entrada> ITenumo> Concat <Toma> (este <EnTienda <Entrada> IEnumerable
<Testidad> en segundo lugar)
• public static Boolean Contiene <TSource> (esta fuente IEnumerable <TSource>, valor de
TSource)
• public static Boolean Contiene <TSource> (este IEnumerable <TSource> fuente, TSource
valor, IEqualityComparer <TSource> comparador)
• cuenta estática pública Int32 <TSource> (esta fuente IEnumerable <TSource>)
• cuenta estática pública Int32 Count <TSource> (esta fuente IEnumerable <TSource>, Func
<TSource, Boolean> predicate)
• Public static IEnumerable <TSource> DefaultIfEmpty <TSource> (esta fuente IEnumerable
<TSource>)
• public static IEnumerable <TSource> DefaultIfEmpty <TSource> (esta fuente IEnumerable
<TSource>, TSource defaultValue)
• Public static IEnumerable <TSource> Distinct <TSource> (esta fuente IEnumerable
<TSource>)
• IEnumerable estático público <TSource> Distintivo <TSource> (este IEnumerable
<TSource> fuente, IEqualityComparer <TSource> comparador)
• TSA estática pública ElementAt <TSource> (esta IEnumerable <TSource> fuente, índice
Int32)
• TSource estático público ElementAtOrDefault <TSource> (este IEnumerable <TSource>
fuente, índice Int32)
• Public static IEnumerable <TResult> Empty <TResult> ()
• IEnumerable estático público <TSource> Excepto <TSource> (este IEnumerable <TSource>
primero, IEnumerable <TSource> segundo)
• IEnumerable estático público <TSource> Excepto <TSource> (este IEnumerable <TSource>
primero, IEnumerable <TSource> segundo, IEqualityComparer <TSource> comparador)
• fuente estática pública TSource First <TSource> (esta fuente IEnumerable <TSource>)
• Public static TSource First <TSource> (este IEnumerable <TSource> source, Func
<TSource, Boolean> predicate)
https://riptutorial.com/es/home 125
• público estático TSource FirstOrDefault <TSource> (esta fuente IEnumerable <TSource>)
• public static TSource FirstOrDefault <TSource> (este IEnumerable <TSource> source, Func
<TSource, Boolean> predicate)
• IEnumerable estático público <IGrouping <TKey, TSource >> GroupBy <TSource, TKey>
(este IEnumerable <TSource> source, Func <TSource, TKey> keySelector)
• IEnumerable estático público <IGrouping <TKey, TSource >> GroupBy <TSource, TKey>
(este IEnumerable <TSource> fuente, Func <TSource, TKey> keySelector,
IEqualityComparer <TKey> comparador)
• público IEnumerable estático <IGrouping <TKey, TElement >> GroupBy <TSource, TKey,
TElement> (esta fuente IEnumerable <TSource>, Func <TSource, TKey> keySelector, Func
<TSource, TElement> elementSelector)
• public static IEnumerable <IGrouping <TKey, TElement >> GroupBy <TSource, TKey,
TElement> (esta fuente IEnumerable <TSource>, Func <TSource, TKey> keySelector, Func
<TSource, TElement> elementSelector, IEqualityComparer <TKey> comparer)
• público Estática IEnumerable <TResult> GrupoBy <TSource, TKey, TResult> (esta fuente
IEnumerable <TSource>, Func <TSource, TKey> keySelector, Func <TKey, IEnumerable
<TSource>, TResult> resultSelector)
• public static IEnumerable <TResult> GroupBy <TSource, TKey, TResult> (esta fuente
IEnumerable <TSource>, Func <TSource, TKey> keySelector, Func <TKey, IEnumerable
<TSource>, TResult> resultSelector, IEqualityComparer <TKey> comparer)
• public static IEnumerable <TResult> GroupBy <TSource, TKey, TElement, TResult> (esta
fuente IEnumerable <TSource>, Func <TSource, TKey> keySelector, Func <TSource,
TElement> elementSelector, Func <TKey, IEnumerable <TElement>, TResult >
resultSelector)
• public static IEnumerable <TResult> GroupBy <TSource, TKey, TElement, TResult> (esta
fuente IEnumerable <TSource>, Func <TSource, TKey> keySelector, Func <TSource,
TElement> elementSelector, Func <TKey, IEnumerable <TElement>, TResult >
resultSelector, comparador IEqualityComparer <TKey>)
• public static IEnumerable <TResult> GroupJoin <TOuter, TInner, TKey, TResult> (este
IEnumerable <TOuter> external, IEnumerable <TInner> inner, Func <Touter, TKey>
outerKeySelector, Func <TInner, TKey> innerKeySelector, Func <Touter, IEnumerable
<TInner>, TResult> resultSelector)
• public static IEnumerable <TResult> GroupJoin <TOuter, TInner, TKey, TResult> (este
IEnumerable <TOuter> external, IEnumerable <TInner> inner, Func <Touter, TKey>
outerKeySelector, Func <TInner, TKey> innerKeySelector, Func <Touter, IEnumerable
<TInner>, TResult> resultSelector, IEqualityComparer <TKey> comparer)
• IEnumerable estático público <TSource> Intersect <TSource> (este IEnumerable <TSource>
primero, IEnumerable <TSource> segundo)
• IEnumerable estático público <TSource> Intersect <TSource> (este IEnumerable <TSource>
primero, IEnumerable <TSource> segundo, IEqualityComparer <TSource> comparador)
• public static IEnumerable <TResult> Join <TOuter, TInner, TKey, TResult> (este
IEnumerable <TOuter> external, IEnumerable <TInner> inner, Func <TOuter, TKey>
outerKeySelector, Func <TInner, TKey> innerKeySelector, Func <Touter, TInner, TResult>
resultSelector)
• public static IEnumerable <TResult> Join <TOuter, TInner, TKey, TResult> (este
IEnumerable <TOuter> external, IEnumerable <TInner> inner, Func <TOuter, TKey>
https://riptutorial.com/es/home 126
outerKeySelector, Func <TInner, TKey> innerKeySelector, Func <Touter, TInner, TResult>
resultSelector, IEqualityComparer <TKey> comparer)
• Último <TSource> de esta fuente estática pública (esta fuente <TSource> de IEnumerable)
• Último recurso público de TSource <TSource> (este IEnumerable <TSource> source, Func
<TSource, Boolean> predicate)
• público estático TSource LastOrDefault <TSource> (esta fuente IEnumerable <TSource>)
• público estático TSource LastOrDefault <TSource> (este IEnumerable <TSource> fuente,
Func <TSource, Boolean> predicado)
• pública estática Int64 LongCount <TSource> (esta fuente IEnumerable <TSource>)
• pública estática Int64 LongCount <TSource> (esta fuente IEnumerable <TSource>, Func
<TSource, Boolean> predicate)
• Máximo decimal estático público (esta fuente <Decimal> IEnumerable)
• doble estática pública (esta fuente <Double> de IEnumerable)
• pública estática Int32 Max (esta fuente IEnumerable <Int32>)
• pública estática Int64 Max (esta fuente IEnumerable <Int64>)
• Nullable estática pública <Decimal> Máx (este IEnumerable <Nullable <Decimal>> fuente)
• Nullable estático público <Double> Max (este IEnumerable <Nullable <Double>> fuente)
• Nullable estática pública <Int32> Máx (este IEnumerable <Nullable <Int32>> fuente)
• Nullable estática pública <Int64> Máx (este IEnumerable <Nullable <Int64>> fuente)
• Nullable estático público <Single> Máx (este IEnumerable <Nullable <Single>> fuente)
• único estático público (esta fuente <Single> de IEnumerable)
• public static TSource Max <TSource> (esta fuente IEnumerable <TSource>)
• public static Decimal Max <TSource> (este IEnumerable <TSource> source, Func
<TSource, Decimal> selector)
• public static Double Max <TSource> (esta fuente IEnumerable <TSource>, Func <TSource,
Double> selector)
• public static Int32 Max <TSource> (esta fuente IEnumerable <TSource>, Func <TSource,
Int32> selector)
• pública estática Int64 Max <TSource> (esta fuente IEnumerable <TSource>, Func
<TSource, Int64> selector)
• pública estática Nullable <Decimal> Max <TSource> (esta fuente IEnumerable <TSource>,
Func <TSource, Nullable <Decimal>> selector)
• pública estática Nullable <Double> Max <TSource> (esta fuente IEnumerable <TSource>,
Func <TSource, Nullable <Double>> selector)
• Public static Nullable <Int32> Max <TSource> (esta fuente IEnumerable <TSource>, Func
<TSource, Nullable <Int32>> selector)
• Public static Nullable <Int64> Max <TSource> (esta fuente IEnumerable <TSource>, Func
<TSource, Nullable <Int64>> selector)
• pública estática Nullable <Single> Max <TSource> (esta fuente IEnumerable <TSource>,
Func <TSource, Nullable <Single>> selector)
• public static Single Max <TSource> (este IEnumerable <TSource> source, Func <TSource,
Single> selector)
• public static TResult Max <TSource, TResult> (esta fuente IEnumerable <TSource>, Func
<TSource, TResult> selector)
• Minimal Decimal estático público (esta fuente <Decimal> IEnumerable)
• Double Min estática pública (esta fuente <Double> de IEnumerable)
https://riptutorial.com/es/home 127
• Int32 Min público estático (esta fuente IEnumerable <Int32>)
• Int64 público estático (esta fuente IEnumerable <Int64>)
• Nullable estático público <Decimal> Min (este IEnumerable <Nullable <Decimal>> fuente)
• Nullable estático público <Double> Min (este IEnumerable <Nullable <Double>> fuente)
• Nullable estática pública <Int32> Min (este IEnumerable <Nullable <Int32>> fuente)
• Nullable estática pública <Int64> Min (este IEnumerable <Nullable <Int64>> fuente)
• Nullable estático público <Single> Min (este IEnumerable <Nullable <Single>> fuente)
• pública (solo) estática mínima (esta fuente <Single> de IEnumerable)
• <<source Source> (esta fuente IEnumerable <TSource>) estática pública
• Minimal Decimal estático público <TSource> (este IEnumerable <TSource> source, Func
<TSource, Decimal> selector)
• pública estática Double Min <TSource> (esta fuente IEnumerable <TSource>, Func
<TSource, Double> selector)
• <> Fuente pública estática Int32 Min <TSource> (esta fuente IEnumerable <TSource>, Func
<TSource, Int32> selector)
• Int64 público estático Int64 Min <TSource> (este IEnumerable <TSource> fuente, Func
<TSource, Int64> selector)
• Nullable estática pública <Decimal> Min <TSource> (este <Entrada <EntradaDeIerable
<Funcional, Func <TSource, <Decimal> Nullable>> selector))
• Public static Nullable <Double> Min <TSource> (esta fuente IEnumerable <TSource>, Func
<TSource, Nullable <Double>> selector)
• Nullable estática pública <Int32> Min <TSource> (este IEnumerable <TSource> fuente, Func
<TSource, Nullable <Int32>> selector)
• Nullable estático público <Int64> Min <TSource> (este IEnumerable <TSource> fuente, Func
<TSource, Nullable <Int64>> selector)
• Nullable estática pública <Single> Min <TSource> (esta IEnumerable <TSource> fuente,
Func <TSource, Nullable <Single>> selector)
• Public static Single Min <TSource> (este IEnumerable <TSource> source, Func <TSource,
Single> selector)
• público estático TResult Min <TSource, TResult> (este IEnumerable <TSource> fuente,
Func <TSource, TResult> selector)
• IEnumerable estático público <TResult> OfType <TResult> (esta fuente IEnumerable)
• Public static IOrderedEnumerable <TSource> OrderBy <TSource, TKey> (esta fuente
IEnumerable <TSource>, Func <TSource, TKey> keySelector)
• Public static IOrderedEnumerable <TSource> OrderBy <TSource, TKey> (esta fuente
IEnumerable <TSource>, Func <TSource, TKey> keySelector, IComparer <TKey>
comparador)
• Public static IOrderedEnumerable <TSource> OrderByDescending <TSource, TKey> (esta
fuente IEnumerable <TSource>, Func <TSource, TKey> keySelector)
• Public static IOrderedEnumerable <TSource> OrderByDescending <TSource, TKey> (esta
fuente IEnumerable <TSource>, Func <TSource, TKey> keySelector, IComparer <TKey>
comparador)
• Intervalo IEnumerable estático público <Int32> (Int32 start, Int32 count)
• Public static IEnumerable <TResult> Repetir <TResult> (elemento TResult, conteo Int32)
• Public static IEnumerable <TSource> Reverse <TSource> (esta fuente IEnumerable
<TSource>)
https://riptutorial.com/es/home 128
• IEnumerable estático público <TResult> Seleccione <TSource, TResult> (este <Entrada>
<En este fuente IEnumerable, Func <TSource, TResult> selector)
• IEnumerable estático público <TResult> Seleccione <TSource, TResult> (esta fuente
<TSource> IEnumerable>, Func <TSource, Int32, TResult> selector)
• public static IEnumerable <TResult> SelectMany <TSource, TResult> (esta fuente
IEnumerable <TSource>, Func <TSource, IEnumerable <TResult>> selector)
• public static IEnumerable <TResult> SelectMany <TSource, TResult> (esta fuente
IEnumerable <TSource>, Func <TSource, Int32, IEnumerable <TResult>> selector)
• public static IEnumerable <TResult> SelectMany <TSource, TCollection, TResult> (esta
fuente IEnumerable <TSource>, Func <TSource, IEnumerable <TCollection>>
collectionSelector, Func <TSource, TCollection, TResult> resultadoSelector)
• public static IEnumerable <TResult> SelectMany <TSource, TCollection, TResult> (esta
fuente IEnumerable <TSource>, Func <TSource, Int32, IEnumerable <TCollection>>
collectionSelector, Func <TSource, TCollection, TResult> resultSelector)
• Public static Boolean SequenceEqual <TSource> (este IEnumerable <TSource> primero,
IEnumerable <TSource> segundo)
• Public static Boolean SequenceEqual <TSource> (este IEnumerable <TSource> primero,
IEnumerable <TSource> segundo, IEqualityComparer <TSource> comparer)
• Public static TSource Single <TSource> (esta fuente IEnumerable <TSource>)
• Fuente estática pública TSource Single <TSource> (esta fuente <Entrada>, <Entrada>,
Func <TSource, Boolean> predicado)
• público estático TSource SingleOrDefault <TSource> (esta fuente IEnumerable <TSource>)
• público estático TSource SingleOrDefault <TSource> (este IEnumerable <TSource> fuente,
Func <TSource, Boolean> predicado)
• ITenumerable <TSource> estático público Omitir <TSource> (esta fuente <TSource>
IEnumerable, cuenta Int32)
• público IEnumerable I <> <> <> Fuente> Omitir> <<<Fuente> (<En este <I> IEnumerable
<TSource>, Func <TSource, Boolean> predicate)
• público IEnumerable I <> <> <> Fuente> Omitir> <<<Fuente> (<En este <I> <I> Fuente <En
<> <> <<<<Source Source>, Func <TSource, Int32, Boolean> predicate)
• Suma decimal estática pública (esta fuente <Decimal> IEnumerable)
• Suma estática pública doble (esta fuente <Double> de IEnumerable)
• suma estática pública Int32 (esta fuente IEnumerable <Int32>)
• Suma estática pública Int64 (esta fuente IEnumerable <Int64>)
• Public static Nullable <Decimal> Sum (este IEnumerable <Nullable <Decimal>> source)
• Public static Nullable <Double> Sum (este IEnumerable <Nullable <Double>> source)
• Public static Nullable <Int32> Sum (este IEnumerable <Nullable <Int32>> source)
• Nullable estática pública <Int64> Suma (esta IEnumerable <Nullable <Int64>> fuente)
• Public static Nullable <Single> Sum (este IEnumerable <Nullable <Single>> fuente)
• Suma única estática pública (esta fuente IEnumerable <Single>)
• Suma Decimal estática pública <TSource> (esta fuente <Entrada> IEnumerable, Func
<TSource, Decimal> selector)
• Public static Double Sum <TSource> (este IEnumerable <TSource> source, Func <TSource,
Double> selector)
• Public static Int32 Sum <TSource> (este IEnumerable <TSource> source, Func <TSource,
Int32> selector)
https://riptutorial.com/es/home 129
• Public static Int64 Sum <TSource> (esta fuente IEnumerable <TSource>, Func <TSource,
Int64> selector)
• Public static Nullable <Decimal> Sum <TSource> (este IEnumerable <TSource> source,
Func <TSource, Nullable <Decimal>> selector)
• Public static Nullable <Double> Sum <TSource> (este IEnumerable <TSource> source,
Func <TSource, Nullable <Double>> selector)
• Public static Nullable <Int32> Sum <TSource> (esta fuente IEnumerable <TSource>, Func
<TSource, Nullable <Int32>> selector)
• Public static Nullable <Int64> Sum <TSource> (esta fuente IEnumerable <TSource>, Func
<TSource, Nullable <Int64>> selector)
• pública estática Nullable <Single> Sum <TSource> (esta fuente IEnumerable <TSource>,
Func <TSource, Nullable <Single>> selector)
• Public static Single Sum <TSource> (este IEnumerable <TSource> source, Func <TSource,
Single> selector)
• ITenumerable <TSource> estático público Tomar <TSource> (esta fuente <TSource>
IEnumerable, cuenta de Int32)
• público IEnumerable <TSource> TakeWhile <TSource> (este IEnumerable <TSource>
fuente, Func <TSource, Boolean> predicado)
• público IEnumerable <TSource> TakeWhile <TSource> (este IEnumerable <TSource>
fuente, Func <TSource, Int32, Boolean> predicado)
• Public static IOrderedEnumerable <TSource> ThenBy <TSource, TKey> (esta fuente
IOrderedEnumerable <TSource>, Func <TSource, TKey> keySelector)
• Public static IOrderedEnumerable <TSource> ThenBy <TSource, TKey> (esta fuente
IOrderedEnumerable <TSource>, Func <TSource, TKey> keySelector, IComparer <TKey>
comparador)
• public static IOrderedEnumerable <TSource> ThenByDescending <TSource, TKey> (esta
fuente IOrderedEnumerable <TSource>, Func <TSource, TKey> keySelector)
• public static IOrderedEnumerable <TSource> ThenByDescending <TSource, TKey> (esta
fuente IOrderedEnumerable <TSource>, Func <TSource, TKey> keySelector, IComparer
<TKey> comparer)
• TSource estático público [] ToArray <TSource> (esta fuente IEnumerable <TSource>)
• Diccionario estático público <TKey, TSource> ToDictionary <TSource, TKey> (este
<Entrada <Entrada> fuente, Func <TSource, TKey> keySelector)
• Diccionario estático público <TKey, TSource> ToDictionary <TSource, TKey> (esta fuente
IEnumerable <TSource>, Func <TSource, TKey> keySelector, IEqualityComparer <TKey>
comparador)
• Diccionario estático público <TKey, TElement> ToDictionary <TSource, TKey, TElement>
(esta fuente <EntradaTenerable ITenumerable, Func <TSource, TKey> keySelector, Func
<TSource, TElement> elementSelector)
• diccionario estático público <TKey, TElement> ToDictionary <TSource, TKey, TElement>
(este <Entrada <EntradaTenera <TSource>, Func <TSource, TKey> keySelector, Func
<TSource, TElement> elementSelector, IEqualityComparer <TKey> comparador)
• Lista estática pública <TSource> ToList <TSource> (esta fuente IEnumerable <TSource>)
• pública ILookup estática <TKey, TSource> ToLookup <TSource, TKey> (esta fuente <Ted>
IEnumerable <TSource, Func <TSource, TKey> keySelector)
• pública ILookup estática <TKey, TSource> ToLookup <TSource, TKey> (esta fuente
https://riptutorial.com/es/home 130
IEnumerable <TSource>, Func <TSource, TKey> keySelector, IEqualityComparer <TKey>
comparador)
• pública ILookup estática <TKey, TElement> ToLookup <TSource, TKey, TElement> (esta
fuente IEnumerable <TSource>, Func <TSource, TKey> keySelector, Func <TSource,
TElement> elementSelector)
• pública estática ILookup <TKey, TElement> ToLookup <TSource, TKey, TElement> (esta
fuente enumerable <TSource>, Func <TSource, TKey> keySelector, Func <TSource,
TElement> elementSelector, IEqualityComparer <TKey> comparador)
• Unión <TSource> estática pública <TSource> <TSource> (primero <TSource> IEnumerable
<TSource>, <TSource> IEnumerable <TSource)
• Public <B> <TSource> Union <TSource> estática pública (esta <TSource> IEnumerable
<TSource> en primer lugar, <TSource> IEnumerable <TSource>, comparador
IEqualityComparer <TSource>)
• ITenumerable <TSource> estático público Donde <TSource> (este <Tedource>
IEnumerable fuente, Func <TSource, booleano> predicado)
• ITenumerable <TSource> estático público Donde <TSource> (este <Tedource>
IEnumerable fuente, Func <TSource, Int32, booleano> predicado)
• público IEnumerable IEnumerable <TResult> Zip <TFirst, TSecond, TResult> (este
IEnumerable <TFirst> primero, IEnumerable <TSecond> segundo, Func <TFirst, TSecond,
TResult> resultSelector)
Observaciones
• Véase también LINQ .
Los métodos incorporados de LINQ son métodos de extensión para la IEnumerable<T> que viven
en la clase System.Linq.Enumerable en el ensamblado System.Core . Están disponibles en .NET
Framework 3.5 y versiones posteriores.
Mientras que los métodos estándar de LINQ pueden trabajar en cualquier IEnumerable<T> ,
incluyendo las matrices simples y List<T> s, también pueden ser utilizados en los objetos de base
de datos, donde el conjunto de expresiones LINQ se puede transformar en muchos casos a SQL
si la objeto de datos lo soporta. Ver LINQ to SQL .
Para los métodos que comparan objetos (como Contains y Except ), IEquatable<T>.Equals se usa si
el tipo T de la colección implementa esa interfaz. De lo contrario, se utilizan los Equals y
GetHashCode estándar del tipo (posiblemente anulados de las implementaciones de Object
predeterminadas). También hay sobrecargas para estos métodos que permiten especificar un
IEqualityComparer<T> .
Para los métodos ...OrDefault , el default(T) se utiliza para generar valores predeterminados.
https://riptutorial.com/es/home 131
Evaluación perezosa
Prácticamente todas las consultas que devuelven un IEnumerable<T> no se evalúan de inmediato;
en cambio, la lógica se retrasa hasta que la consulta se repite. Una implicación es que cada vez
que alguien itera sobre un IEnumerable<T> creado a partir de una de estas consultas, por ejemplo,
.Where() , se repite la lógica de consulta completa. Si el predicado es de larga ejecución, esto
puede ser una causa de problemas de rendimiento.
Una solución simple (cuando sabe o puede controlar el tamaño aproximado de la secuencia
resultante) es amortiguar completamente los resultados utilizando .ToArray() o .ToList() .
.ToDictionary() o .ToLookup() pueden cumplir la misma función. Por supuesto, también se puede
iterar en toda la secuencia y almacenar en búfer los elementos de acuerdo con otra lógica
personalizada.
ToArray() o ToList() ?
Tanto .ToArray() como .ToList() recorren todos los elementos de una IEnumerable<T> y guardan
los resultados en una colección almacenada en la memoria. Utilice las siguientes pautas para
determinar cuál elegir:
Examples
Seleccione (mapa)
https://riptutorial.com/es/home 132
//Foo,Bar,Fizz,Buzz
Este tipo de función se suele llamar map en los lenguajes de programación funcionales.
Donde (filtro)
Este método devuelve un IEnumerable con todos los elementos que cumplen con la expresión
lambda
Ejemplo
Salida:
Foo, Fizz
Ver demostración
Orden por
//2,4,3,1
OrderByDescending
https://riptutorial.com/es/home 133
Console.WriteLine(string.Join(",", personsSortedByNameDescending.Select(p =>
p.Id).ToArray()));
//1,3,4,2
Contiene
Excepto
Console.WriteLine(string.Join(",", result));
//1, 2, 3, 4, 5, 7, 9
Intersecarse
Console.WriteLine(string.Join(",", numbers5to10));
//5,6,7,8,9,10
Concat
Console.WriteLine(string.Join(",", numbers1to8));
//1,2,3,4,5,4,5,6,7,8
Tenga en cuenta que los duplicados se mantienen en el resultado. Si esto no es deseable, usa
Union lugar.
Primero (encontrar)
https://riptutorial.com/es/home 134
var firstNumber = numbers.First();
Console.WriteLine(firstNumber); //1
Soltero
Último
LastOrDefault
https://riptutorial.com/es/home 135
var lastNegativeNumber = numbers.LastOrDefault(n => n < 0);
Console.WriteLine(lastNegativeNumber); //0
SingleOrDefault
FirstOrDefault
https://riptutorial.com/es/home 136
Alguna
Devuelve true si la colección tiene algún elemento que cumpla con la condición en la expresión
lambda:
Todos
Tenga en cuenta que el método All funciona al verificar que el primer elemento se evalúe como
false según el predicado. Por lo tanto, el método devolverá true para cualquier predicado en el
caso de que el conjunto esté vacío:
Enumerable.Select devuelve un elemento de salida para cada elemento de entrada. Mientras que
Enumerable.SelectMany produce un número variable de elementos de salida para cada elemento de
entrada. Esto significa que la secuencia de salida puede contener más o menos elementos de los
que estaban en la secuencia de entrada.
https://riptutorial.com/es/home 137
Ejemplo
class Invoice
{
public int Id { get; set; }
}
class Customer
{
public Invoice[] Invoices {get;set;}
}
Console.WriteLine(
string.Join(",", allInvoicesFromAllCustomers.Select(i => i.Id).ToArray()));
Salida:
1,2,3,4,5,6
Ver demostración
Enumerable.SelectManytambién se puede lograr con una consulta basada en la sintaxis usando dos
cláusulas consecutivas from :
var allInvoicesFromAllCustomers
= from customer in customers
from invoice in customer.Invoices
select invoice;
Suma
https://riptutorial.com/es/home 138
var sumOfAllNumbers = numbers.Sum();
Console.WriteLine(sumOfAllNumbers); //10
Omitir
Omitir enumerará los primeros N elementos sin devolverlos. Una vez que se alcanza el número
de artículo N + 1, Skip comienza a devolver cada artículo enumerado:
//3,4,5
Tomar
//1,2,3
SecuenciaEqual
Marcha atrás
Console.WriteLine(string.Join(",", reversed.ToArray()));
https://riptutorial.com/es/home 139
//5,4,3,2,1
De tipo
Console.WriteLine(string.Join(",", numbers.ToArray()));
//1,2,3,4
Max
Min
Promedio
https://riptutorial.com/es/home 140
var cities = new[] {
new {Population = 1000},
new {Population = 2000},
new {Population = 4000}
};
Cremallera
.NET 4.0
Console.WriteLine(string.Join(",", sums));
//11,22,33,44,55
Distinto
Console.WriteLine(string.Join(",", distinctNumbers));
//1,2,3,4,5
Agrupar por
https://riptutorial.com/es/home 141
Agrupe las facturas por país, generando un nuevo objeto con el número de registro, el total
pagado y el promedio pagado
Al diccionario
Especificar solo una función de selector de clave creará un Dictionary<TKey,TVal> con TKey el tipo
de retorno del selector de clave, TVal el tipo de objeto original y el objeto original como valor
almacenado.
Console.WriteLine(personsById[1].Name); //Fizz
Console.WriteLine(personsById[2].Name); //Buzz
https://riptutorial.com/es/home 142
var namesById = persons.ToDictionary(p => p.Id, p => p.Name);
//namesById is a Dictionary<int,string>
Console.WriteLine(namesById[3]); //Foo
Console.WriteLine(namesById[4]); //Bar
Como se indicó anteriormente, las claves devueltas por el selector de claves deben ser únicas. Lo
siguiente lanzará una excepción.
Si no se puede dar una clave única para la colección de origen, considere usar ToLookup en su
lugar. En la superficie, ToLookup se comporta de manera similar a ToDictionary, sin embargo, en
la búsqueda resultante, cada clave se empareja con una colección de valores con claves
coincidentes.
Unión
Console.WriteLine(string.Join(",", numbers1to8));
//1,2,3,4,5,6,7,8
Tenga en cuenta que los duplicados se eliminan del resultado. Si esto no es deseable, use Concat
en Concat lugar.
ToArray
Console.WriteLine(someNumbers.GetType().Name);
//WhereArrayIterator`1
Console.WriteLine(someNumbersArray.GetType().Name);
//Int32[]
Listar
https://riptutorial.com/es/home 143
var numbers = new[] {1,2,3,4,5,6,7,8,9,10};
var someNumbers = numbers.Where(n => n < 6);
Console.WriteLine(someNumbers.GetType().Name);
//WhereArrayIterator`1
Console.WriteLine(
someNumbersList.GetType().Name + " - " +
someNumbersList.GetType().GetGenericArguments()[0].Name);
//List`1 - Int32
Contar
Elemento
ElementAtOrDefault
SkipWhile
https://riptutorial.com/es/home 144
Console.WriteLine(string.Join(",", oddNumbers.ToArray()));
//1,3,5,7
TakeWhile
Console.WriteLine(string.Join(",", evenNumbers.ToArray()));
//2,4,6
DefaultIfEmpty
Agregado (pliegue)
Console.WriteLine(commaSeparatedElements); //1,2,3,4,5,
Console.WriteLine(commaSeparatedElements2.ToString()); //1,2,3,4,5,
https://riptutorial.com/es/home 145
var commaSeparatedElements3 = elements.Aggregate(
seed: new StringBuilder(),
func: (seed, element) => seed.Append($"{element},"),
resultSelector: (seed) => seed.ToString());
Console.WriteLine(commaSeparatedElements3); //1,2,3,4,5,
Console.WriteLine(commaSeparatedElements4); //12,3,4,5,
Para buscar
Unirse
class Developer
{
public int Id { get; set; }
public string Name { get; set; }
}
class Project
{
public int DeveloperId { get; set; }
public string Name { get; set; }
}
https://riptutorial.com/es/home 146
Id = 2,
Name = "Barfizz"
}
};
Grupo unirse a
class Developer
{
public int Id { get; set; }
public string Name { get; set; }
}
class Project
{
public int DeveloperId { get; set; }
public string Name { get; set; }
}
https://riptutorial.com/es/home 147
Id = 1,
Name = "Foobuzz"
},
new Developer {
Id = 2,
Name = "Barfizz"
}
};
Emitir
Cast es diferente de los otros métodos de Enumerable en que es un método de extensión para
IEnumerable , no para IEnumerable<T> . Por lo tanto, se puede utilizar para convertir instancias del
primero en instancias del último.
https://riptutorial.com/es/home 148
Esto funciona como se esperaba:
Vacío
Este IEnumerable vacío se almacena en caché para cada tipo T, de modo que:
Entonces por
ThenBy solo se puede utilizar después de una cláusula OrderBy que permite realizar pedidos
utilizando varios criterios
Distancia
https://riptutorial.com/es/home 149
Los dos parámetros para Range son el primer número y el conteo de elementos a producir (no el
último número).
// prints 1,2,3,4,5,6,7,8,9,10
Console.WriteLine(string.Join(",", Enumerable.Range(1, 10)));
// prints 10,11,12,13,14
Console.WriteLine(string.Join(",", Enumerable.Range(10, 5)));
class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
class Pet
{
public string Name { get; set; }
public Person Owner { get; set; }
}
var query =
from person in people
join pet in pets on person equals pet.Owner into gj
from subpet in gj.DefaultIfEmpty()
select new
{
person.FirstName,
PetName = subpet?.Name ?? "-" // Use - if he has no pet
};
Repetir
Enumerable.Repeat genera una secuencia de un valor repetido. En este ejemplo se genera "Hola" 4
veces.
https://riptutorial.com/es/home 150
Console.WriteLine(item);
}
/* output:
Hello
Hello
Hello
Hello
*/
https://riptutorial.com/es/home 151
Capítulo 37: Los diccionarios
Examples
Enumerar un diccionario
Usando valores
https://riptutorial.com/es/home 152
Agregando a un diccionario
// To safely add items (check to ensure item does not already exist - would throw)
if(!dict.ContainsKey(3))
{
dict.Add(3, "Third");
}
A diferencia del método Add que lanza una excepción, si una clave ya está contenida en el
diccionario, el indexador simplemente reemplaza el valor existente.
Es posible que desee leer el valor de la entrada con la clave 1. Si no existe una clave, obtener un
valor arrojará la KeyNotFoundException , por lo que es posible que primero desee verificarlo con
ContainsKey :
if (dict.ContainsKey(1))
Console.WriteLine(dict[1]);
Esto tiene una desventaja: buscará en su diccionario dos veces (una para verificar la existencia y
otra para leer el valor). Para un diccionario grande, esto puede afectar el rendimiento.
Afortunadamente ambas operaciones se pueden realizar juntas:
https://riptutorial.com/es/home 153
string value;
if (dict.TryGetValue(1, out value))
Console.WriteLine(value);
Representa una colección segura de subprocesos de pares clave / valor a los que se
puede acceder mediante varios subprocesos simultáneamente.
Agregando o Actualizando
Es posible que se sorprenda de que no haya un método Add , pero en su lugar hay AddOrUpdate con
2 sobrecargas:
(1) AddOrUpdate(TKey key, TValue, Func<TKey, TValue, TValue> addValue) - Agrega un par de clave /
valor si la clave aún no existe, o actualiza un par de clave / valor usando la función especificada si
la clave ya existe.
Agregar o actualizar un valor, sin importar cuál era el valor si ya estaba presente para la clave
dada (1):
Usando la sobrecarga (2) también podemos agregar un nuevo valor usando una fábrica:
https://riptutorial.com/es/home 154
string addedValue3 = dict.AddOrUpdate(1, (key) => key == 1 ? "First" : "Not First",
(updateKey, valueOld) => $"{valueOld} Updated");
Obteniendo valor
Obtener un valor es el mismo que con el Dictionary<TKey,TValue> :
Obtenga el valor con la clave 2, o agregue el valor "Segundo" si la clave no está presente:
using System;
using System.Collections.Generic;
using System.Linq;
https://riptutorial.com/es/home 155
Eliminar de un diccionario
La ejecución de este código elimina la clave 2 y su valor del diccionario. Remove devuelve un valor
booleano que indica si la clave especificada se encontró y se eliminó del diccionario. Si la clave
no existe en el diccionario, no se elimina nada del diccionario y se devuelve falso (no se lanza
ninguna excepción).
Esto no eliminará la clave. Simplemente reemplazará el valor anterior con un valor null .
Para eliminar todas las claves y valores de un diccionario, use el método Clear .
dict.Clear();
Después de ejecutar Clear el Count del diccionario será 0, pero la capacidad interna permanecerá
sin cambios.
ContainsKey (TKey)
Para verificar si un Dictionary tiene una clave específica, puede llamar al método
ContainsKey(TKey) y proporcionar la clave del tipo TKey . El método devuelve un valor bool cuando
la clave existe en el diccionario. Para la muestra:
https://riptutorial.com/es/home 156
if (dictionary.ContainsKey("C2"))
{
// exists
}
Diccionario a la lista
Problema
ConcurrentDictionary brilla cuando se trata de devolver instantáneamente las claves existentes de
la memoria caché, en su mayoría sin bloqueo, y compitiendo en un nivel granular. Pero, ¿qué
sucede si la creación del objeto es realmente costosa y supera el costo del cambio de contexto y
se producen algunos errores de caché?
Si se solicita la misma clave de varios subprocesos, uno de los objetos resultantes de las
operaciones de colisión se agregará finalmente a la colección, y los otros se tirarán,
desperdiciando el recurso de la CPU para crear el objeto y el recurso de memoria para almacenar
el objeto temporalmente . También se podrían desperdiciar otros recursos. Esto es realmente
malo.
Solución
Podemos combinar ConcurrentDictionary<TKey, TValue> con Lazy<TValue> . La idea es que el
método ConcurrentDictionary GetOrAdd solo puede devolver el valor que realmente se agregó a
la colección. Los objetos perezosos perdidos también se pueden desperdiciar en este caso, pero
eso no es un gran problema, ya que el objeto perezoso en sí es relativamente barato. La
https://riptutorial.com/es/home 157
propiedad Value de la perezosa perdedora nunca se solicita, porque somos inteligentes para
solicitar solo la propiedad Value de la que realmente se agregó a la colección, la que se devolvió
del método GetOrAdd:
https://riptutorial.com/es/home 158
Capítulo 38: Marco de Extensibilidad
Gestionado
Observaciones
Una de las grandes ventajas de MEF sobre otras tecnologías que admiten el patrón de inversión
de control es que admite la resolución de dependencias que no se conocen en el momento del
diseño, sin necesidad de mucha configuración (si la hay).
Además, todos los ejemplos (básicos) los utilizan como objetos de negocio de muestra:
using System.Collections.ObjectModel;
namespace Demo
{
public sealed class User
{
public User(int id, string name)
{
this.Id = id;
this.Name = name;
}
Examples
Exportando un Tipo (Básico)
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel.Composition;
namespace Demo
{
[Export(typeof(IUserProvider))]
public sealed class UserProvider : IUserProvider
{
https://riptutorial.com/es/home 159
public ReadOnlyCollection<User> GetAllUsers()
{
return new List<User>
{
new User(0, "admin"),
new User(1, "Dennis"),
new User(2, "Samantha"),
}.AsReadOnly();
}
}
}
Esto podría definirse virtualmente en cualquier lugar; todo lo que importa es que la aplicación
sepa dónde buscarla (a través de los ComposablePartCatalogs que crea).
Importando (Básico)
using System;
using System.ComponentModel.Composition;
namespace Demo
{
public sealed class UserWriter
{
[Import(typeof(IUserProvider))]
private IUserProvider userProvider;
Este es un tipo que depende de un IUserProvider , que podría definirse en cualquier lugar. Al igual
que en el ejemplo anterior, todo lo que importa es que la aplicación sabe dónde buscar la
exportación correspondiente (a través de los ComposablePartCatalogs que crea).
Conectando (Básico)
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
namespace Demo
{
public static class Program
{
public static void Main()
{
using (var catalog = new ApplicationCatalog())
https://riptutorial.com/es/home 160
using (var exportProvider = new CatalogExportProvider(catalog))
using (var container = new CompositionContainer(exportProvider))
{
exportProvider.SourceProvider = container;
Se pueden usar otros tipos de catálogos (por ejemplo, DirectoryCatalog ) en lugar de (o además
de) ApplicationCatalog , para buscar en otros lugares las exportaciones que satisfacen las
importaciones.
https://riptutorial.com/es/home 161
Capítulo 39: Para cada
Observaciones
Utilizarlo en absoluto?
Podría argumentar que la intención de .NET framework es que las consultas no tengan ningún
efecto secundario y que el método ForEach esté, por definición, causando un efecto secundario. Es
posible que su código sea más fácil de mantener y más fácil de probar si, en su lugar, utiliza un
simple foreach .
Examples
Llamar a un método en un objeto en una lista
customers.Add(new Customer());
customers.Add(new Customer());
ToList primero
Se evaluará la enumeración (o consulta), copiando los resultados en una nueva lista o llamando a
la base de datos. El método se llama a continuación en cada elemento.
Este método tiene una sobrecarga de uso de memoria evidente, ya que se crea una lista
intermedia.
Método de extensión
https://riptutorial.com/es/home 162
Escribe un método de extensión:
Utilizar:
Precaución: los métodos LINQ de Framework se han diseñado con la intención de ser puros , lo
que significa que no producen efectos secundarios. El único propósito del método ForEach es
producir efectos secundarios, y se desvía de los otros métodos en este aspecto. Puede
considerar simplemente usar un bucle foreach simple en su lugar.
https://riptutorial.com/es/home 163
Capítulo 40: Procesamiento paralelo
utilizando .Net framework
Introducción
Este tema trata sobre la programación de varios núcleos utilizando la biblioteca paralela de tareas
con .NET framework. La biblioteca paralela de tareas le permite escribir código legible por
humanos y se ajusta con la cantidad de Cores disponibles. Por lo tanto, puede estar seguro de
que su software se actualizará automáticamente con el entorno de actualización.
Examples
Extensiones paralelas
Se han introducido extensiones paralelas junto con la biblioteca paralela de tareas para lograr el
paralelismo de datos. El paralelismo de datos se refiere a escenarios en los que la misma
operación se realiza de forma simultánea (es decir, en paralelo) en elementos de una colección o
matriz de origen. .NET proporciona nuevas construcciones para lograr el paralelismo de datos
mediante el uso de construcciones Parallel.For y Parallel.Foreach.
//Sequential version
Process(item);
// Parallel equivalent
https://riptutorial.com/es/home 164
Capítulo 41: Proceso y ajuste de afinidad del
hilo
Parámetros
Parámetro Detalles
Observaciones
La afinidad del procesador de un subproceso es el conjunto de procesadores con los que tiene
una relación. En otras palabras, aquellos que pueden ser programados para ejecutarse.
La afinidad del procesador representa cada procesador como un bit. El bit 0 representa el
procesador uno, el bit 1 representa el procesador dos y así sucesivamente.
Examples
Obtener máscara de afinidad de proceso
return processorAffinity;
}
https://riptutorial.com/es/home 165
return myProcess;
}
Ejemplo de uso:
Console.ReadKey();
}
// Output:
// Process Test.vshost Affinity Mask is : 11111111
Ejemplo de uso:
Console.ReadKey();
}
// Output :
// Process Test.vshost Old Affinity Mask is : 11111111
// Process Test.vshost New Affinity Mask is : 10101010
https://riptutorial.com/es/home 166
Capítulo 42: Puertos seriales
Examples
Operación básica
Lectura asíncrona
using System.IO.Ports;
namespace TextEchoService
{
class Program
{
static void Main(string[] args)
{
https://riptutorial.com/es/home 167
var serialPort = new SerialPort("COM1", 9600, Parity.Even, 8, StopBits.One);
serialPort.Open();
string message = "";
while (message != "quit")
{
message = serialPort.ReadLine();
serialPort.WriteLine(message);
}
serialPort.Close();
}
}
}
using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Text;
using System.Threading;
namespace AsyncReceiver
{
class Program
{
const byte STX = 0x02;
const byte ETX = 0x03;
const byte ACK = 0x06;
const byte NAK = 0x15;
static ManualResetEvent terminateService = new ManualResetEvent(false);
static readonly object eventLock = new object();
static List<byte> unprocessedBuffer = null;
https://riptutorial.com/es/home 168
var port = (SerialPort)sender;
int bytesToRead = port.BytesToRead;
if (bytesToRead > buffer.Length)
Array.Resize(ref buffer, bytesToRead);
int bytesRead = port.Read(buffer, 0, bytesToRead);
ProcessBuffer(buffer, bytesRead);
break;
case SerialData.Eof:
terminateService.Set();
break;
}
}
}
static void ErrorReceivedHandler(object sender, SerialErrorReceivedEventArgs e)
{
lock (eventLock)
if (e.EventType == SerialError.TXFull)
{
Console.WriteLine("Error: TXFull. Can't handle this!");
terminateService.Set();
}
else
{
Console.WriteLine("Error: {0}. Resetting everything", e.EventType);
var port = (SerialPort)sender;
port.DiscardInBuffer();
port.DiscardOutBuffer();
unprocessedBuffer = null;
port.Write(new byte[] { NAK }, 0, 1);
}
}
Este programa espera los mensajes incluidos en los bytes STX y ETX y genera el texto que viene
entre ellos. Todo lo demás se desecha. En el desbordamiento del búfer de escritura se detiene.
En otros errores, restablece los buffers de entrada y salida y espera otros mensajes.
El código ilustra:
https://riptutorial.com/es/home 169
• Lectura asíncrona de puerto serie (ver SerialPort.DataReceived use).
• Procesamiento de errores del puerto serie (consulte SerialPort.ErrorReceived use).
• Implementación de protocolo no basado en mensajes de texto.
• Lectura parcial de mensajes.
○El evento SerialPort.DataReceived puede suceder antes de que llegue el mensaje
completo (hasta ETX ). Es posible que el mensaje completo tampoco esté disponible en
el búfer de entrada (SerialPort.Read (..., ..., port.BytesToRead) lee solo una parte del
mensaje). En este caso, guardamos la parte recibida ( unprocessedBuffer ) y seguimos
esperando otros datos.
• Tratar con varios mensajes que vienen de una sola vez.
○El evento SerialPort.DataReceived puede suceder solo después de que el otro extremo
haya enviado varios mensajes.
https://riptutorial.com/es/home 170
Capítulo 43: ReadOnlyCollections
Observaciones
Una ReadOnlyCollection proporciona una vista de solo lectura a una colección existente (la
'colección de origen').
Use ReadOnlyCollection cuando desee permitir que un código externo vea su colección sin poder
modificarla, pero aún así podrá modificar la colección usted mismo.
Ver también
• ObservableCollection<T>
• ReadOnlyObservableCollection<T>
ReadOnlyCollections vs ImmutableCollection
Una ReadOnlyCollection difiere de una ImmutableCollection en que no puede editar una
ImmutableCollection una vez que la creó; siempre contendrá n elementos, y no se pueden
reemplazar ni reordenar. Una ReadOnlyCollection , por otro lado, no se puede editar directamente,
pero los elementos todavía se pueden agregar / eliminar / reordenar usando la colección de
origen.
Examples
Creando una colección ReadOnly
Usando el constructor
Una ReadOnlyCollection se crea al pasar un objeto IList existente al constructor:
Usando LINQ
https://riptutorial.com/es/home 171
Adicionalmente, LINQ proporciona un método de extensión AsReadOnly() para objetos IList :
Nota
Normalmente, desea mantener la colección de origen de forma privada y permitir el acceso
público a ReadOnlyCollection . Si bien puede crear una ReadOnlyCollection de una lista en línea, no
podrá modificar la colección después de crearla.
Si se encuentra haciendo esto, puede considerar usar otra estructura de datos, como
ImmutableCollection .
Ver demostración
Si la colección de origen es de un tipo que no es inmutable, los elementos a los que se accede a
través de ReadOnlyCollection se pueden modificar.
https://riptutorial.com/es/home 172
}
// The customer can't add or remove items, but they can change
// the price of an item, even though it is a ReadOnlyCollection
customerPreview.Last().Price = 0.25m;
Ver demostración
https://riptutorial.com/es/home 173
Capítulo 44: Recolección de basura
Introducción
En .Net, los objetos creados con new () se asignan en el montón administrado. Estos objetos
nunca son finalizados explícitamente por el programa que los usa; en su lugar, este proceso es
controlado por el .Net Garbage Collector.
Algunos de los ejemplos a continuación son "casos de laboratorio" para mostrar el recolector de
basura en el trabajo y algunos detalles significativos de su comportamiento, mientras que otros se
centran en cómo preparar clases para el manejo adecuado por parte del recolector de basura.
Observaciones
El recolector de basura tiene como objetivo reducir el costo del programa en términos de memoria
asignada, pero hacerlo tiene un costo en términos de tiempo de procesamiento. Para lograr un
buen compromiso general, hay una serie de optimizaciones que deben tenerse en cuenta al
programar con el recolector de basura en mente:
Examples
Un ejemplo básico de recolección (basura)
~FinalizableObject()
https://riptutorial.com/es/home 174
{
Console.WriteLine("Instance finalized");
}
}
<namespace>.FinalizableObject initialized
Si no ocurre nada más, el objeto no se finaliza hasta que el programa finaliza (lo que libera todos
los objetos en el montón administrado, finalizando estos en el proceso).
<namespace>.FinalizableObject initialized
<namespace>.FinalizableObject finalized
Esta vez, tan pronto como se invocó el recolector de basura, el objeto no utilizado (también
conocido como "muerto") se finalizó y se liberó del montón administrado.
Regla de oro: cuando se produce la recolección de basura, los "objetos vivos" son aquellos que
aún están en uso, mientras que los "objetos muertos" son aquellos que ya no se usan (cualquier
variable o campo que haga referencia a ellos, si los hubiera, ha quedado fuera del alcance antes
de que ocurra la recolección) .
La salida será:
<namespace>.FinalizableObject1 initialized
https://riptutorial.com/es/home 175
<namespace>.FinalizableObject2 initialized
<namespace>.FinalizableObject1 finalized
¿Qué sucede si dos (o varios) objetos muertos se hacen referencia entre sí? Esto se muestra en
el ejemplo a continuación, suponiendo que OtherObject es una propiedad pública de
FinalizableObject:
<namespace>.FinalizedObject1 initialized
<namespace>.FinalizedObject2 initialized
<namespace>.FinalizedObject1 finalized
<namespace>.FinalizedObject2 finalized
Los dos objetos se finalizan y se liberan del montón administrado a pesar de que se hacen
referencia entre sí (porque no existe ninguna otra referencia para ninguno de ellos desde un
objeto realmente vivo).
Referencias débiles
Las referencias débiles son ... referencias, a otros objetos (también conocidos como "objetivos"),
pero "débiles", ya que no evitan que esos objetos se recojan de basura. En otras palabras, las
referencias débiles no cuentan cuando el recolector de basura evalúa los objetos como "vivos" o
"muertos".
El siguiente código:
Produce la salida:
<namespace>.FinalizableObject initialized
<namespace>.FinalizableObject finalized
https://riptutorial.com/es/home 176
El objeto se libera del montón administrado a pesar de que la variable WeakReference hace
referencia a él (aún en el ámbito cuando se invocó el recolector de basura).
La versión genérica de WeakReference está disponible desde .Net 4.5. Todas las versiones de
framework proporcionan una versión no genérica, sin tipo, que se construye de la misma manera
y se verifica de la siguiente manera:
https://riptutorial.com/es/home 177
medio para garantizar que los recursos pesados en memoria se liberen tan pronto como el objeto
ya no se use. La "captura" es que no existe una garantía sólida de que se invoque el método
Dispose () (a diferencia de los finalizadores que siempre se invocan al final de la vida útil del
objeto).
Otro escenario es declarar una clase para ser instanciada por el marco. En este caso, la nueva
clase generalmente hereda una clase base, por ejemplo en MVC uno crea una clase de
controlador como una subclase de System.Web.Mvc.ControllerBase. Cuando la clase base
implementa una interfaz IDisposable, este es un buen indicio de que el marco invocaría a Dispose
() correctamente, pero nuevamente no hay una garantía sólida.
Por lo tanto, Dispose () no es un sustituto para un finalizador; en cambio, los dos deben ser
usados para diferentes propósitos:
Como Dispose () y los finalizadores tienen objetivos diferentes, una clase que administre recursos
pesados de memoria externa debería implementar ambos. La consecuencia es escribir la clase
para que maneje bien dos posibles escenarios:
Una solución es escribir el código de limpieza de tal manera que ejecutarlo una o dos veces
produzca el mismo resultado que ejecutarlo solo una vez. La viabilidad depende de la naturaleza
de la limpieza, por ejemplo:
https://riptutorial.com/es/home 178
efecto por lo que funciona
• Actualizar algún "conteo de uso" es peligroso y produciría un resultado incorrecto cuando se
lo llama dos veces en lugar de una vez.
Una solución más segura es garantizar por diseño que el código de limpieza se llame una vez y
solo una vez, independientemente del contexto externo. Esto se puede lograr de la "manera
clásica" usando una bandera dedicada:
~DisposableFinalizable1() { Cleanup(); }
https://riptutorial.com/es/home 179
Capítulo 45: Redes
Observaciones
Ver también: Clientes HTTP
Examples
Chat TCP básico (TcpListener, TcpClient, NetworkStream)
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
class TcpChat
{
static void Main(string[] args)
{
if(args.Length == 0)
{
Console.WriteLine("Basic TCP chat");
Console.WriteLine();
Console.WriteLine("Usage:");
Console.WriteLine("tcpchat server <port>");
Console.WriteLine("tcpchat client <url> <port>");
return;
}
try
{
Run(args);
}
catch(IOException)
{
Console.WriteLine("--- Connection lost");
}
catch(SocketException ex)
{
Console.WriteLine("--- Can't connect: " + ex.Message);
}
}
if(args[0].StartsWith("s", StringComparison.InvariantCultureIgnoreCase))
{
var port = int.Parse(args[1]);
var listener = new TcpListener(IPAddress.Any, port);
https://riptutorial.com/es/home 180
listener.Start();
Console.WriteLine("--- Waiting for a connection...");
client = listener.AcceptTcpClient();
}
else
{
var hostName = args[1];
var port = int.Parse(args[2]);
client = new TcpClient();
client.Connect(hostName, port);
}
stream = client.GetStream();
Console.WriteLine("--- Connected. Start typing! (exit with Ctrl-C)");
while(true)
{
if(Console.KeyAvailable)
{
var lineToSend = Console.ReadLine();
var bytesToSend = encoding.GetBytes(lineToSend + "\r\n");
stream.Write(bytesToSend, 0, bytesToSend.Length);
stream.Flush();
}
if (stream.DataAvailable)
{
var receivedBytesCount = stream.Read(buffer, 0, buffer.Length);
var receivedString = encoding.GetString(buffer, 0, receivedBytesCount);
Console.Write(receivedString);
}
}
}
}
using System;
using System.Globalization;
using System.Linq;
using System.Net;
using System.Net.Sockets;
class SntpClient
{
const int SntpPort = 123;
static DateTime BaseDate = new DateTime(1900, 1, 1);
https://riptutorial.com/es/home 181
Console.WriteLine("(append .5 for an extra half an hour)");
return;
}
double localTimeZoneInHours = 0;
if(args.Length > 1)
localTimeZoneInHours = double.Parse(args[1], CultureInfo.InvariantCulture);
udpClient.Send(
dgram: sntpRequest,
bytes: sntpRequest.Length,
hostname: args[0],
port: SntpPort);
byte[] sntpResponse;
try
{
IPEndPoint remoteEndpoint = null;
sntpResponse = udpClient.Receive(ref remoteEndpoint);
}
catch(SocketException)
{
Console.WriteLine("*** No response received from the server");
return;
}
uint numberOfSeconds;
if(BitConverter.IsLittleEndian)
numberOfSeconds = BitConverter.ToUInt32(
sntpResponse.Skip(40).Take(4).Reverse().ToArray()
,0);
else
numberOfSeconds = BitConverter.ToUInt32(sntpResponse, 40);
Console.WriteLine(
$"Current date in server: {date:yyyy-MM-dd HH:mm:ss}
UTC{localTimeZoneInHours:+0.#;-0.#;.}");
}
}
https://riptutorial.com/es/home 182
Capítulo 46: Reflexión
Examples
¿Qué es una asamblea?
using System.Reflection;
Los ensamblajes se autodocumentan: no solo contienen tipos, métodos y su código IL, sino
también los metadatos necesarios para inspeccionarlos y consumirlos, tanto en la compilación
como en el tiempo de ejecución:
Console.WriteLine(typeof(int).Assembly.FullName);
// Will print: "mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
T variable = Activator.CreateInstance(typeof(T));
https://riptutorial.com/es/home 183
T variable = Activator.CreateInstance(typeof(T), arg1, arg2);
Digamos que tenemos una clase con Classy que tiene propiedad Propertua
Los atributos pueden ser útiles para denotar metadatos en enumeraciones. Obtener el valor de
esto puede ser lento, por lo que es importante almacenar en caché los resultados.
// Get the custom attributes of the type desired found on the struct.
T[] attribs = (T[])fieldInfo.GetCustomAttributes(typeof(T), false);
return result;
}
https://riptutorial.com/es/home 184
}
return true;
}
return accumulator;
}
}
Nota: este ejemplo realiza una comparación basada en campos (ignora los campos estáticos y
las propiedades) para simplificar
https://riptutorial.com/es/home 185
Capítulo 47: Serialización JSON
Observaciones
JavaScriptSerializer vs Json.NET
Examples
Deserialización utilizando
System.Web.Script.Serialization.JavaScriptSerializer
using System.Collections;
using System.Web.Script.Serialization;
// ...
// ...
https://riptutorial.com/es/home 186
string rawJSON = "{\"Name\":\"Fibonacci Sequence\",\"Numbers\":[0, 1, 1, 2, 3, 5, 8, 13]}";
[JsonObject("person")]
public class Person
{
[JsonProperty("name")]
public string PersonName { get; set; }
[JsonProperty("age")]
public int PersonAge { get; set; }
[JsonIgnore]
public string Address { get; set; }
}
Person person = new Person { PersonName = "Andrius", PersonAge = 99, Address = "Some address"
};
string rawJson = JsonConvert.SerializeObject(person);
Console.WriteLine(rawJson); // {"name":"Andrius","age":99}
Observe cómo las propiedades (y las clases) se pueden decorar con atributos para cambiar su
apariencia en la cadena json resultante o para eliminarlas de la cadena json (JsonIgnore).
Puede encontrar más información sobre los atributos de serialización de Json.NET aquí .
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
Console.WriteLine(json); // {"name":"Andrius","age":99}
}
https://riptutorial.com/es/home 187
Serialización-Deserialización utilizando Newtonsoft.Json
A diferencia de los otros ayudantes, este utiliza ayudantes de clase estática para serializar y
deserializar, por lo que es un poco más fácil de usar que los demás.
using Newtonsoft.Json;
Vinculación dinámica
De serialización
Observe que las claves en el objeto rawJson se han convertido en variables miembro en el objeto
dinámico.
Esto es útil en los casos en que una aplicación puede aceptar / producir diferentes formatos de
JSON. Sin embargo, se sugiere utilizar un nivel adicional de validación para la cadena Json o
para el objeto dinámico generado como resultado de la serialización / deserialización.
Este serializador tiene algunas características interesantes que el serializador .net json
predeterminado no tiene, como el manejo de valor nulo, solo necesita crear el
JsonSerializerSettings :
https://riptutorial.com/es/home 188
Otro problema serio del serializador en .net es el bucle de referencia automática. En el caso de un
estudiante que está inscrito en un curso, su instancia tiene una propiedad del curso y un curso
tiene una colección de estudiantes que significa una List<Student> que creará un bucle de
referencia. Puedes manejar esto con JsonSerializerSettings :
https://riptutorial.com/es/home 189
Capítulo 48: Servidores HTTP
Examples
Servidor de archivos HTTP básico de solo lectura (HttpListener)
Notas:
Para simplificar, se asume que los nombres de los archivos son todos ASCII (para la parte del
nombre del archivo en el encabezado Content-Disposition ) y los errores de acceso a los archivos
no se manejan.
using System;
using System.IO;
using System.Net;
class HttpFileServer
{
private static HttpListenerResponse response;
private static HttpListener listener;
private static string baseFilesystemPath;
if(args.Length < 2)
{
Console.WriteLine("Basic read-only HTTP file server");
Console.WriteLine();
Console.WriteLine("Usage: httpfileserver <base filesystem path> <port>");
Console.WriteLine("Request format: http://url:port/path/to/file.ext");
return;
}
baseFilesystemPath = Path.GetFullPath(args[0]);
var port = int.Parse(args[1]);
https://riptutorial.com/es/home 190
ServerLoop();
}
catch(Exception ex)
{
Console.WriteLine(ex);
if(response != null)
{
SendErrorResponse(500, "Internal server error");
}
}
}
if (request.HttpMethod.ToUpper() != "GET")
{
SendErrorResponse(405, "Method must be GET");
continue;
}
response.OutputStream.Close();
response = null;
Console.WriteLine(" Ok!");
}
}
https://riptutorial.com/es/home 191
Console.WriteLine("*** Sent error: {0} {1}", statusCode, statusResponse);
}
}
1 - Cree una carpeta vacía, contendrá los archivos creados en los siguientes pasos.
2 - Cree un archivo llamado project.json con el siguiente contenido (ajuste el número de puerto y
rootDirectory según corresponda):
{
"dependencies": {
"Microsoft.AspNet.Server.Kestrel": "1.0.0-rc1-final",
"Microsoft.AspNet.StaticFiles": "1.0.0-rc1-final"
},
"commands": {
"web": "Microsoft.AspNet.Server.Kestrel --server.urls http://localhost:60000"
},
"frameworks": {
"dnxcore50": { }
},
"fileServer": {
"rootDirectory": "c:\\users\\username\\Documents"
}
}
using System;
using Microsoft.AspNet.Builder;
using Microsoft.AspNet.FileProviders;
using Microsoft.AspNet.Hosting;
using Microsoft.AspNet.StaticFiles;
using Microsoft.Extensions.Configuration;
https://riptutorial.com/es/home 192
context.Context.Response.Headers.Add(
"Content-Disposition",
$"Attachment; filename=\"{context.File.Name}\"");
};
app.UseStaticFiles(options);
}
}
Nota: estos comandos deben ejecutarse solo una vez. Use la dnvm list para verificar el número
real de la última versión instalada del CLR principal.
Para simplificar, se asume que los nombres de los archivos son todos ASCII (para la parte del
nombre del archivo en el encabezado Content-Disposition) y los errores de acceso a los archivos
no se manejan.
https://riptutorial.com/es/home 193
Capítulo 49: Sistema de envasado NuGet
Observaciones
NuGet.org :
Examples
Instalación del Gestor de paquetes NuGet
Para poder administrar los paquetes de sus proyectos, necesita NuGet Package Manager. Esta
es una extensión de Visual Studio, que se explica en los documentos oficiales: Instalación y
actualización de NuGet Client .
A partir de Visual Studio 2012, NuGet se incluye en todas las ediciones y se puede usar desde:
Herramientas -> NuGet Package Manager -> Package Manager Console.
Lo haces a través del menú Herramientas de Visual Studio, haciendo clic en Extensiones y
actualizaciones:
https://riptutorial.com/es/home 194
Esto instala tanto la GUI:
Cuando hace clic con el botón derecho en un proyecto (o en su carpeta Referencias), puede
hacer clic en la opción "Administrar paquetes NuGet ...". Esto muestra el cuadro de diálogo
Administrador de paquetes .
https://riptutorial.com/es/home 195
Gestionando paquetes a través de la consola.
Haga clic en los menús Herramientas -> NuGet Package Manager -> Package Manager Console
para mostrar la consola en su IDE. Documentación oficial aquí .
Aquí puede emitir, entre otros, install-package comandos install-package que instalan el paquete
introducido en el "Proyecto predeterminado" seleccionado actualmente:
Install-Package Elmah
Actualizando un paquete
https://riptutorial.com/es/home 196
Para actualizar un paquete usa el siguiente comando:
donde EntityFramework es el nombre del paquete que se actualizará. Tenga en cuenta que la
actualización se ejecutará para todos los proyectos, por lo que es diferente de Install-Package
EntityFramework que se instalaría solo en el "Proyecto predeterminado".
Desinstalar un paquete
Es común que la compañía configure su propio servidor nuget para la distribución de paquetes en
diferentes equipos.
1. Vaya al Explorador de soluciones y haga clic en el botón derecho del mouse, luego elija
Manage NuGet Packages for Solution
https://riptutorial.com/es/home 197
2. En la ventana que se abre, haga clic en Settings
3. Haga clic en + en la esquina superior derecha y luego agregue el nombre y la URL que
apunta a su servidor local de nuget.
https://riptutorial.com/es/home 198
desinstalar una versión específica del paquete
https://riptutorial.com/es/home 199
Capítulo 50: SpeechRecognitionEngine clase
para reconocer el habla
Sintaxis
• SpeechRecognitionEngine ()
• SpeechRecognitionEngine.LoadGrammar (gramática gramatical)
• SpeechRecognitionEngine.SetInputToDefaultAudioDevice ()
• SpeechRecognitionEngine.RecognizeAsync (modo RecognizeMode)
• Constructor de gramática()
• GrammarBuilder.Append (Opciones de opciones)
• Opciones (cadena de parámetros [] opciones)
• Gramática (constructor GrammarBuilder)
Parámetros
RecognizeAsync :
Detalles
Parámetros
GrammarBuilder.Append :
Detalles
Parámetros
Constructor de Choices :
Detalles
Parámetros
Constructor de Grammar :
Detalles
parámetro
https://riptutorial.com/es/home 200
Observaciones
Para usar SpeechRecognitionEngine , su versión de Windows debe tener habilitado el
reconocimiento de voz.
Debe agregar una referencia a System.Speech.dll antes de poder usar las clases de voz.
Examples
Reconocimiento asíncrono de voz para dictado de texto libre.
using System.Speech.Recognition;
// ...
https://riptutorial.com/es/home 201
Capítulo 51: System.IO
Examples
Leyendo un archivo de texto usando StreamReader
string fileData;
Tenga en cuenta que esta sobrecarga del constructor StreamReader realiza alguna detección de
codificación automática, que puede o no ser compatible con la codificación real utilizada en el
archivo.
Tenga en cuenta que hay algunos métodos convenientes que leen todo el texto del archivo
disponible en la clase System.IO.File , a saber, File.ReadAllText(path) y File.ReadAllLines(path) .
• En la primera línea, leemos todos los datos en el archivo como una cadena.
• En la segunda línea, leemos los datos del archivo en una matriz de cadenas. Cada línea del
archivo se convierte en un elemento de la matriz.
• En el tercero leemos los bytes del archivo.
A continuación, veamos tres métodos diferentes de agregar datos a un archivo. Si el archivo que
especifica no existe, cada método creará automáticamente el archivo antes de intentar agregarle
los datos.
https://riptutorial.com/es/home 202
• En la primera línea, simplemente agregamos una cadena al final del archivo especificado.
• En la segunda línea, agregamos cada elemento de la matriz a una nueva línea en el
archivo.
• Finalmente, en la tercera línea, usamos File.AppendText para abrir un streamwriter que
agregará los datos que se le escriban.
Y por último, veamos tres métodos diferentes para escribir datos en un archivo. La diferencia
entre agregar y escribir es que la escritura sobrescribe los datos en el archivo mientras se
agrega agrega a los datos en el archivo. Si el archivo que especifica no existe, cada método
creará automáticamente el archivo antes de intentar escribirle los datos.
using System.IO.Ports;
string[] ports = SerialPort.GetPortNames();
for (int i = 0; i < ports.Length; i++)
{
Console.WriteLine(ports[i]);
}
using System.IO.Ports;
SerialPort port = new SerialPort();
SerialPort port = new SerialPort("COM 1"); ;
SerialPort port = new SerialPort("COM 1", 9600);
NOTA : Esas son solo tres de las siete sobrecargas del constructor para el tipo SerialPort.
https://riptutorial.com/es/home 203
Leyendo
Escritura
Sin embargo, también puede enviar datos de esta manera cuando sea necesario:
//Note that you can swap out the byte-array with a char-array if you so choose.
byte[] data = new byte[1] { 255 };
port.Write(data, 0, data.Length);
https://riptutorial.com/es/home 204
Capítulo 52: System.Net.Mail
Observaciones
Es importante disponer un System.Net.MailMessage porque todos los archivos adjuntos
contienen un Stream y estos Streams se deben liberar lo antes posible. La declaración de uso
garantiza que el objeto desechable se deseche también en caso de excepciones
Examples
MailMessage
Aquí está el ejemplo de creación de mensaje de correo con archivos adjuntos. Después de crear
enviamos este mensaje con la ayuda de la clase SmtpClient . Aquí se utiliza el puerto
predeterminado de 25.
MyMail.Subject = subject;
MyMail.IsBodyHtml = true;
MyMail.Body = body;
MyMail.Priority = MailPriority.Normal;
https://riptutorial.com/es/home 205
if (Attachment != null && Attachment.Any())
{
System.Net.Mail.Attachment attachment;
foreach (var item in Attachment)
{
attachment = new System.Net.Mail.Attachment(item);
MyMail.Attachments.Add(attachment);
}
}
smtpMailObj.Send(MyMail);
return true;
}
}
catch
{
return false;
}
}
}
MailMessage representa un mensaje de correo que puede enviarse aún más usando la clase
SmtpClient . Se pueden agregar varios archivos adjuntos (archivos) al mensaje de correo.
using System.Net.Mail;
https://riptutorial.com/es/home 206
Capítulo 53: System.Reflection.Emit
namespace
Examples
Creando un ensamblaje dinámicamente.
using System;
using System.Reflection;
using System.Reflection.Emit;
class DemoAssemblyBuilder
{
public static void Main()
{
// An assembly consists of one or more modules, each of which
// contains zero or more types. This code creates a single-module
// assembly, the most common case. The module contains one type,
// named "MyDynamicType", that has a private field, a property
// that gets and sets the private field, constructors that
// initialize the private field, and a method that multiplies
// a user-supplied number by the private field value and returns
// the result. In C# the type might look like this:
/*
public class MyDynamicType
{
private int m_number;
https://riptutorial.com/es/home 207
ModuleBuilder mb =
ab.DefineDynamicModule(aName.Name, aName.Name + ".dll");
TypeBuilder tb = mb.DefineType(
"MyDynamicType",
TypeAttributes.Public);
ILGenerator il = mbMyMethod.GetILGenerator();
il.Emit(OpCodes.Ldarg_0); // Load this - always the first argument of any instance
method
il.Emit(OpCodes.Ldfld, fbNumber);
il.Emit(OpCodes.Ldarg_1); // Load the integer argument
il.Emit(OpCodes.Mul); // Multiply the two numbers with no overflow checking
il.Emit(OpCodes.Ret); // Return
// Next, we build the property. This involves building the property itself, as well as
the
// getter and setter methods.
PropertyBuilder pbNumber = tb.DefineProperty(
"Number", // Name
PropertyAttributes.None,
typeof(int), // Type of the property
new Type[0]); // Types of indices, if any
https://riptutorial.com/es/home 208
il = mbGetNumber.GetILGenerator();
il.Emit(OpCodes.Ldarg_0); // Load this
il.Emit(OpCodes.Ldfld, fbNumber); // Load the value of this.m_number
il.Emit(OpCodes.Ret); // Return the value
pbNumber.SetGetMethod(mbGetNumber);
// The types from the assembly can be used directly using reflection, or we can save
the assembly to use as a reference
object ourInstance = Activator.CreateInstance(ourType);
Console.WriteLine(ourType.GetProperty("Number").GetValue(ourInstance)); // 42
// Save the assembly for use elsewhere. This is very useful for debugging - you can
use e.g. ILSpy to look at the equivalent IL/C# code.
ab.Save(@"DynamicAssemblyExample.dll");
// Using newly created type
var myDynamicType = tb.CreateType();
var myDynamicTypeInstance = Activator.CreateInstance(myDynamicType);
Console.WriteLine(myDynamicTypeInstance.GetType()); // MyDynamicType
Console.WriteLine(numberField.GetValue(myDynamicTypeInstance)); // 10
}
}
https://riptutorial.com/es/home 209
Capítulo 54:
System.Runtime.Caching.MemoryCache
(ObjectCache)
Examples
Agregar elemento a caché (conjunto)
La función de ajuste inserta una entrada de caché en el caché utilizando una instancia de
CacheItem para proporcionar la clave y el valor de la entrada de caché.
System.Runtime.Caching.MemoryCache (ObjectCache)
Esta función obtiene el caché de formulario del elemento existente, y si el elemento no existe en
el caché, recuperará el elemento según la función valueFetchFactory.
//returns existing item form cache or add the new value if it does not exist.
https://riptutorial.com/es/home 210
var cachedItem = _cacheContainer.AddOrGetExisting(key, newValue, policy) as
Lazy<TValue>;
https://riptutorial.com/es/home 211
Capítulo 55: Tipos personalizados
Observaciones
Normalmente, una struct se usa solo cuando el rendimiento es muy importante. Dado que los
tipos de valor viven en la pila, se puede acceder a ellos mucho más rápido que las clases. Sin
embargo, la pila tiene mucho menos espacio que el montón, por lo que las estructuras deben
mantenerse pequeñas (Microsoft recomienda que las struct ocupen más de 16 bytes).
Una class es el tipo más usado (de estos tres) en C #, y generalmente es lo que debe ir primero.
Se utiliza una enum siempre que pueda tener una lista clara y clara de elementos que solo deben
definirse una vez (en tiempo de compilación). Las enumeraciones son útiles para los
programadores como una referencia liviana a algún valor: en lugar de definir una lista de variables
constant para comparar, puede usar una enumeración y obtener soporte de Intellisense para
asegurarse de que no use accidentalmente un valor incorrecto.
Examples
Definición de Struct
Pasado por valor significa que el valor del parámetro se copia para el método, y cualquier
cambio realizado en el parámetro en el método no se refleja fuera del método. Por ejemplo,
considere el siguiente código, que llama a un método llamado AddNumbers , que pasa las variables
a y b , que son de tipo int , que es un tipo de valor.
int a = 5;
int b = 6;
AddNumbers(a,b);
https://riptutorial.com/es/home 212
}
A pesar de que hemos añadido a 5 x dentro del método, el valor de a se mantiene sin cambios,
porque es un tipo de valor, y eso significa que x era una copia de a 'valor de s, pero en realidad no
a.
Definición de clase
Pasado por referencia significa que una referencia al parámetro se pasa al método, y cualquier
cambio en el parámetro se reflejará fuera del método cuando regrese, porque la referencia es
exactamente el mismo objeto en la memoria . Usemos el mismo ejemplo que antes, pero primero
"envolveremos" los int en una clase.
AddNumbers(instanceOfMyClass);
Definición de enumeración
https://riptutorial.com/es/home 213
dice al compilador que esta clase hereda de la clase
abstracta System.Enum. Las enumeraciones se utilizan para
distintas listas de elementos.
Puede pensar en una enumeración como una forma conveniente de asignar constantes a algún
valor subyacente. La enumeración definida anteriormente declara valores para cada día de la
semana y comienza con 1 . Tuesday se asignaría automáticamente a 2 , el Wednesday a 3 , etc.
Por defecto, las enumeraciones usan int como el tipo subyacente y comienzan en 0, pero puede
usar cualquiera de los siguientes tipos integrales : byte, sbyte, short, ushort, int, uint, long, or
ulong , y puede especificar valores explícitos para cualquier ít. Si algunos elementos se
especifican explícitamente, pero otros no, cada elemento después del último definido se
incrementará en 1.
Volveremos a utilizar este ejemplo echando algún otro valor a un MyEnum de este modo:
int x = 2;
instance = (MyEnum)x; // now 'instance' has a value of MyEnum.Tuesday
Otro tipo de enumeración útil, aunque más complejo, se llama Flags . Al decorar una enumeración
con el atributo Flags , puede asignar una variable más de un valor a la vez. Tenga en cuenta que
al hacer esto debe definir los valores explícitamente en la representación de base 2.
[Flags]
public enum MyEnum
{
Monday = 1,
Tuesday = 2,
Wednesday = 4,
Thursday = 8,
Friday = 16,
Saturday = 32,
Sunday = 64
}
Ahora puede comparar más de un valor a la vez, ya sea utilizando comparaciones a nivel de bits
o, si está utilizando .NET 4.0 o posterior, el método Enum.HasFlag .
https://riptutorial.com/es/home 214
// *both* Monday and Thursday,
// represented by (in binary) 0100.
if (instance.HasFlag(MyEnum.Wednesday))
{
// it doesn't, so this block is skipped
}
else if (instance.HasFlag(MyEnum.Thursday))
{
// it does, so this block is executed
}
Como la clase Enum se subclasifica de System.ValueType , se trata como un tipo de valor y se pasa
por valor, no por referencia. El objeto base se crea en el montón, pero cuando pasa un valor de
enumeración a una llamada de función, una copia del valor que usa el tipo de valor subyacente de
Enum (generalmente System.Int32) se inserta en la pila. El compilador rastrea la asociación entre
este valor y el objeto base que se creó en la pila. Consulte ValueType Class (System) (MSDN)
para obtener más información.
https://riptutorial.com/es/home 215
Capítulo 56: Trabajar con SHA1 en C #
Introducción
En este proyecto, verá cómo trabajar con la función de hash criptográfico SHA1. por ejemplo,
obtener hash de la cadena y cómo romper el hash SHA1. fuente en git hub:
https://github.com/mahdiabasi/SHA1Tool
Examples
#Generar suma de comprobación SHA1 de una función de archivo
https://riptutorial.com/es/home 216
Capítulo 57: Trabajar con SHA1 en C #
Introducción
En este proyecto, verá cómo trabajar con la función de hash criptográfico SHA1. por ejemplo,
obtener hash de la cadena y cómo romper el hash SHA1.
Examples
#Generar la suma de comprobación SHA1 de un archivo
https://riptutorial.com/es/home 217
Capítulo 58: Usando el progreso e IProgress
Examples
Informe de progreso simple
void Main()
{
IProgress<int> p = new Progress<int>(progress =>
{
Console.WriteLine("Running Step: {0}", progress);
});
LongJob(p);
}
Salida:
Running Step: 0
Running Step: 3
Running Step: 4
Running Step: 5
Running Step: 6
Running Step: 7
Running Step: 8
Running Step: 9
Running Step: 2
Running Step: 1
Tenga en cuenta que cuando ejecute este código, es posible que los números salgan
desordenados. Esto se debe a que el IProgress<T>.Report() se ejecuta de forma asíncrona y, por
lo tanto, no es tan adecuado para situaciones en las que el progreso debe informarse en orden.
Utilizando IProgress
https://riptutorial.com/es/home 218
var p1 = new Progress<int>();
p1.Report(1); //compiler error, Progress does not contain method 'Report'
https://riptutorial.com/es/home 219
Capítulo 59: XmlSerializer
Observaciones
No utilice el XmlSerializer para analizar HTML . Para esto, bibliotecas especiales están disponibles
como el HTML Agility Pack.
Examples
Serializar objeto
Deserializar objeto
<Foo>
<Dog/>
</Foo>
https://riptutorial.com/es/home 220
<Store>
<Articles>
<Product/>
<Product/>
</Articles>
</Store>
[XmlIgnore]
public DateTime Birth {get; set;}
[XmlElement(ElementName="Birth")]
public string BirthString
{
get { return Birth.ToString(_birthStringFormat); }
set { Birth = DateTime.ParseExact(value, _birthStringFormat,
CultureInfo.InvariantCulture); }
}
}
De donde venimos
A veces no podemos proporcionar todos los metadatos necesarios para el marco de XmlSerializer
en atributo. Supongamos que tenemos una clase base de objetos serializados, y algunas de las
clases derivadas son desconocidas para la clase base. No podemos colocar un atributo para
todas las clases que no se conocen en el momento del diseño del tipo base. Podríamos tener otro
equipo desarrollando algunas de las clases derivadas.
https://riptutorial.com/es/home 221
var serializerDictionary = Enumerable.Range(0, allTypes.Length)
.ToDictionary (i => allTypes[i], i => allSerializers[i])
En este ejemplo, el tipo Base no tiene conocimiento de sus tipos derivados, lo cual es normal en
OOP.
Haciéndolo eficientemente
Afortunadamente, hay un método que resuelve este problema en particular: suministrar tipos
conocidos para varios serializadores de manera eficiente:
using System;
using System.Collections.Generic;
using System.Xml.Serialization;
using System.Linq;
using System.Linq;
https://riptutorial.com/es/home 222
}
catch (InvalidOperationException e)
{
Console.WriteLine();
Console.WriteLine("This error was anticipated,");
Console.WriteLine("we have not supplied a derived class.");
Console.WriteLine(e);
}
Console.WriteLine("Now trying to serialize with all of the type information:");
SetupSerializers(allTypes);
Serialize(sampleObject);
Console.WriteLine();
Console.WriteLine("Slides down well this time!");
}
Salida:
https://riptutorial.com/es/home 223
Now trying to serialize with all of the type information:
<?xml version="1.0" encoding="utf-16"?>
<Container xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Base xsi:type="Derived">
<JustSomePropInBase>0</JustSomePropInBase>
<JustSomePropInDerived>0</JustSomePropInDerived>
</Base>
</Container>
Slides down well this time!
Este mensaje de error recomienda lo que intentamos evitar (o lo que no podemos hacer en
algunos escenarios): hacer referencia a los tipos derivados de la clase base:
Use the XmlInclude or SoapInclude attribute to specify types that are not known statically.
<Base xsi:type="Derived">
https://riptutorial.com/es/home 224
Creditos
S.
Capítulos Contributors
No
https://riptutorial.com/es/home 225
web
Expresiones regulares
26 BrunoLM, Denuath, Matt dc, tehDorf
(System.Text.RegularExpressions)
https://riptutorial.com/es/home 226
utilizando la internacionalización
inteligente para ASP.NET
43 ReadOnlyCollections tehDorf
https://riptutorial.com/es/home 227
45 Redes Konamiman
System.Runtime.Caching.MemoryCache
54 Guanxi, RamenChef
(ObjectCache)
https://riptutorial.com/es/home 228