【C# Programming】异常处理、泛型

这篇具有很好参考价值的文章主要介绍了【C# Programming】异常处理、泛型。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、异常处理

1.1 多异常类型

        C# 允许代码引发从System.Exception 派生。 例如:

public sealed class TextNumberParser
{
    public static int Parse(string textDigit)
    {
        string[] digitTexts =  { "zero", "one", "two", "three", "four",   "five", "six", "seven", "eight", "nine" };
        int result = Array.IndexOf(digitTexts, textDigit.ToLower());
        if(result < 0)
            throw new ArgumentException(  "The argument did not represent a digit", nameof(textDigit));
        return result;
    }
}

        两个类似的异常是ArgumentNullException 和 NullReferenceException. 一般在解引用null值时,底层触发NullReferenceException。

        参数异常类型(ArgumentException、ArgumentNullException和ArgumentOutRangeException) 一个重要特征是,每个异常都有一个构造器参数,允许实参名标识为一个字符串. C#的规范是, 对于参数类型异常中的参数名称应该使用nameof 操作符。

        不要引发System.SystemException 和它派生的异常类型 System.stackoverflowException, System.OutOfMemoryException, System.Runtime.InteropServices.COMException,     System.ExecutionEngineException 和System. Runtime.InteropServices.SEHException

        不要引发System.Exception 或者System.ApplicationException

        考虑在程序继续执行会变得不安全时调用System.Environment.FailFast()来终止进程。

1.2 捕获异常

        C# 允许使用多个catch 块, 每个catch 块都能定位特定的异常类型。

public static void Main(string[] args)
{
    try 
    {
        // throw new Win32Exception(42);    
        throw new InvalidOperationException("Arbitrary exception");
    }
    catch(Win32Exception exception) 
    when(args.Length == exception.NativeErrorCode)
    {
        //....
    }
    catch(NullReferenceException exception) {
        // Handle NullReferenceException
    }
    catch(ArgumentException exception) {
        // Handle ArgumentException
    }
    catch(InvalidOperationException exception) {
        // Handle ApplicationException
    }
    catch(Exception exception) {
        //…
    }
    finally {
        // Handle any cleanup code here as it runs  regardless of whether there is an exception
    }
}  

        重新引发已存在的异常:如果引发一个特定的异常, 会更新所有的栈信息来匹配新的引发位置。这会造成指示异常最初发生的调用位置所有栈信息丢失。 因此C#只能在catch 语句中重新抛出异常,例如:

public static void Main(string[] args)
{
    //….
    catch(InvalidOperationException exception) 
    {
        bool exceptionHandled  = false ;  
        if (!exceptionHandled )
            throw; 
    }
    //……
}  

        引发现有异常而不替换栈信息:C# 5.0  新增了一种机制,允许引发从前引发的异常而不丢失原始异常中的栈跟踪信息。 这样即使在catch 外也能重新引发异常。System.Runtime.ExceptionServices.ExceptionDispatchInfo 处理这种情况, 例如:

try{
    //....
}
catch(AggregateException exception){
    exception = exeption.Flatten();
    ExceptionDispatchInfo.Capture(exception.InnerException).Throw();
}

1.3 常规catch 块

        从c# 2.0 开始,所有异常(无论是否从System.Exception) 在进入程序集中,都会被包装成从System.Exception 派生。 

        C# 还支持常规catch 块, 即catch {}. 它在行为上和catch(System.Exception exception) 块完全一致,只是没有类型名和变量名。除此之外, 常规catch块必须是所有catch 块的最后一个。

1.4 异常处理的规范

异常处理规范:

  • 只捕获能处理的异常  
  • 不要隐藏未处理异常  
  • 尽可能少使用System.Exception 和常规catch 块  
  • 避免在调用栈较低位置记录或报告异常  
  • 在catch 块中使用throw,而不是 throw <异常对象> 语句  
  • 重新引发不同异常时要谨慎

1.5 自定义异常

        自定义异常的唯一要求是从System.Exception或者它的子类派生。例如:

class  DatabseException: System.Expection {
    public DatabaseException()
    {
        //…..
    } 
    public DatabaseException(string message )
    {
        //…..
    } 
    public DatabaseException(string message, Exception innerException )
    {
        InnerException= innerException;
        //…..
    } 
    public DatabaseException( System.Data.OracleclientException  exception )
    {
        InnerException= innerException;
        //…..
    } 
} 

使用自定义异常时,应遵守以下实践:  

  • 所有异常应该使用“Exception”后缀
  • 通常,所有异常应包含以下三个构造器: 无参构造器、获取一个string 参数的构造器以及同时获取一个字符串和一个内部异常作为参数的构造器,除此之外, 也应允许任何异常数据作为构造器的一部分  
  • 避免使用深的继承类层次结构(一般应小于5级)

二、泛型

2.1 泛型的使用

        类似于C++,C# 中的范型类和结构要求使用尖括号声明泛型类型参数以及指定范型类型实参

public void Sketch()
{
    Stack<Cell> path = new Stack<Cell>();
    Cell currentPosition;
    ConsoleKeyInfo key;    // Added in C# 2.0
    Console.WriteLine("Use arrow keys to draw. X to exit.");
    for(int i = 2; i < Console.WindowHeight; i++)
        Console.WriteLine();
    currentPosition = new Cell(Console.WindowWidth / 2, Console.WindowHeight / 2);
    path.Push(currentPosition);
    FillCell(currentPosition);
    do {
        bool bFill = false;
        key = Move();
        switch(key.Key) {

        case ConsoleKey.Z:
            if(path.Count >= 1)  
            {                
                // Undo the previous Move.
                currentPosition = path.Pop();
                Console.SetCursorPosition(currentPosition.X, currentPosition.Y);
                FillCell(currentPosition, ConsoleColor.Black);
                Undo();
            }
            break;

        case ConsoleKey.DownArrow:
            if(Console.CursorTop < Console.WindowHeight - 2)
                currentPosition = new Cell(Console.CursorLeft, Console.CursorTop + 1);
            bFill =true;
            break;

        case ConsoleKey.UpArrow:
            if(Console.CursorTop > 1)
                currentPosition = new Cell(Console.CursorLeft, Console.CursorTop - 1);
            bFill =true;
            break;

       case ConsoleKey.LeftArrow:
            if(Console.CursorLeft > 1) 
                currentPosition = new Cell(Console.CursorLeft - 1, Console.CursorTop);
            bFill =true;
            break;

       case ConsoleKey.RightArrow:
            if(Console.CursorLeft < Console.WindowWidth - 2) 
                currentPosition = new Cell(Console.CursorLeft + 1, Console.CursorTop);
            bFill =true;
            break;
       default:
            Console.Beep();    // Added in C# 2.0
            break;
       }
       if (bFill){
           path.Push(currentPosition); // Only type Cell allowed in call to Push().
           FillCell(currentPosition);
       }
    } 
    while(key.Key != ConsoleKey.X);  // Use X to quit.
}
private static ConsoleKeyInfo Move() => Console.ReadKey(true);

    private static void Undo() {
        // stub
    }
    private static void FillCell(Cell cell)
    {
        FillCell(cell, ConsoleColor.White);
    }
    private static void FillCell(Cell cell, ConsoleColor color)
    
        Console.SetCursorPosition(cell.X, cell.Y);
        Console.BackgroundColor = color;
        Console.Write(' ');
        Console.SetCursorPosition(cell.X, cell.Y);
        Console.BackgroundColor = ConsoleColor.Black;
    }

public struct Cell
{
    readonly public int X;
    readonly public int Y;
    public Cell(int x, int y)
    {
        X = x;
        Y = y;
    }
}

2.2 简单泛型类的定义

        在定义泛型类时, 仅需在类名之后使用一对尖括号指定类型参数。使用泛型类时, 类型实参将替换所有指定的类型参数。

public class Stack<T>
{
    // Use read-only field prior to C# 6.0
    private T[] InternalItems { get; }

    public void Push(T data)
    {
        //...
    }

    public T Pop()
    {
        //...
        return InternalItems[0];//just for the example. 
    }
}

泛型类的优点:

  • 泛型促进了类型安全。它确保在参数化类中,只有成员明确期望的数据类型才可使用
  • 为泛型类成员使用值类型,不会造成object的装箱操作。
  • C# 泛型缓解了代码膨胀的情况
  • 性能得到了提高
  • 泛型减少了内存消耗
  • 代码的可读性更好  

类型参数的命名规范:

        和方法参数类似,类型参数应具有可描述性,定义泛型类时参数类型名称应包含T 前缀, 例如:public class EntityCollection<TEntity> {           //….     }

2.3 泛型的接口和结构

        C# 支持在语言中全面使用泛型,其中包括接口和结构。语法和类的语法完全相同。 例如:

interface IPair<T>
{
    T First { get; set; }
    T Second { get; set; }
}

        实现接口的语法与非泛型类的语法相同,一个泛型的类型实参可以成为另一个泛型类型的类型参数。

public struct Pair<T> : IPair<T>
{
    public T First { get; set; }
    public T Second { get; set; }
}

2.4 在类中多次实现同一接口

        相同泛型接口的不同构造被看成是不同的类型,所以类或结构能多次实现“同一个”泛型接口。

public interface IContainer<T>
{
    ICollection<T> Items { get;   set;}
}
public class Person : IContainer<Address>, IContainer<Phone>, IContainer<Email> {
    ICollection<Address> IContainer<Address>.Items {
        get {
            //...
            return new List<Address>();
        }
        set { //…  }
    }
    ICollection<Phone> IContainer<Phone>.Items {
        get {
            //...
            return new List<Phone>();
        }
        set { //… }
    }
    ICollection<Email> IContainer<Email>.Items {
        get {
            //...
            return new List<Email>();
        }
        set { //… }
    }
}
public class Address { }     // For example purposes only
public class Phone { }     // For example purposes only
public class Email { }     // For example purposes only

2.5 构造器和析构器的定义

        泛型类或结构的构造器(析构器)不要类型参数。 例如:

public struct Pair<T> : IPair<T>
{
    public Pair(T first, T second)
    {
        First = first;
        Second = second;
    }
    public Pair(T first)
    {
        First = first;
        Second = default(T);  // must be initialized
    }
    public T First { get; set; }
    public T Second { get; set; }    
}

2.6 多个类型参数

        泛型类型可以使用任意数量的类型参数。

interface IPair<TFirst, TSecond>
{
    TFirst First { get; set; }
    TSecond Second { get; set; }
}
public struct Pair<TFirst, TSecond> : IPair<TFirst, TSecond>
{
    public Pair(TFirst first, TSecond second)
    {
        First = first;
        Second = second;
    }
    public TFirst First { get; set; }
    public TSecond Second { get; set; }
}

2.7 元组

        从C# 4.0 开始,CLR 团队定义了9 个新的泛型类型,它们都叫Tuple. 和 Pair<…> 一样, 相同名称可以重用,只要元数不同。

public class Tuple
{ // ... }
public class Tuple<T1> // : IStructuralEquatable, IStructuralComparable, IComparable
{  // ...  }
public class Tuple<T1, T2> // : IStructuralEquatable, IStructuralComparable, IComparable
{  // ...  }
public class Tuple<T1, T2, T3> // : IStructuralEquatable, IStructuralComparable, Comparable
{  // ... }
public class Tuple<T1, T2, T3, T4> // : IStructuralEquatable, IStructuralComparable, IComparable
{  // ... }
public class Tuple<T1, T2, T3, T4, T5> // : IStructuralEquatable, IStructuralComparable, IComparable
{  // ... }
public class Tuple<T1, T2, T3, T4, T5, T6> // : IStructuralEquatable, IStructuralComparable, IComparable
{  // ... }
public class Tuple<T1, T2, T3, T4, T5, T6, T7> // : IStructuralEquatable, IStructuralComparable, IComparable
{  // ... }
public class Tuple<T1, T2, T3, T4, T5, T6, T7, TRest> // : IStructuralEquatable, IStructuralComparable, IComparable
{  // ... }

2.8 嵌套泛型类型

        嵌套类型自动获得包容类型的类型参数,例如: 假如包含类型声明类型参数T,则 类型T也可以在嵌套类型中使用, 如果嵌套类型包含了自己的类型参数T,那么它会隐藏包容类型的同名类型参数。

class Container<T, U>
{
    // Nested classes inherit type parameters.
    // Reusing a type parameter name will cause
    // a warning.
    class Nested<U>
    {
        void Method(T param0, U param1)
        {}
    }
}

        在声明类型参数的类型主体的人和地方都能访问该类型参数。

2.9 约束

        泛型允许为类型参数定义约束,这些约束强迫作为类型实参提供的类型遵守各种规则。

public class BinaryTree<T> {
    public T Item { get; set; }
    public Pair<BinaryTree<T>> SubItems
    {
        get { return _SubItems; }
        set {
            IComparable<T> first;
            first = (IComparable<T>)value.First.Item;
            if(first.CompareTo(value.Second.Item) < 0) {
                //…    // first is less than second.
            }
            else {
                // second is less than or equal to first.
            }
            _SubItems = value;
        }
    }
    private Pair<BinaryTree<T>> _SubItems;
}

        如果BinaryTree<T> 的类型参数没有实现 IComparabe<T> 接口,则会发生执行时错误。

2.10 接口约束

        约束描述了泛型要求的类型参数的特征。为了声明一个约束, 需要使用where 关键字, 后面跟一对参数:要求。 其中, ”参数”必须时泛型类型中声明的一个参数,而”要求” 描述了类型参数要能转换成的类或接口是否必须有默认构造器, 或者是引用类型还是值类型。

        接口约束规定了某个数据类型必须实现某个接口。 例如:

public class BinaryTree<T>
where T : System.IComparable<T> 
{
    public T Item { get; set; }
    public Pair<BinaryTree<T>> SubItems
    {
        get { return _SubItems; }
        set {
            IComparable<T> first = value.First.Item;     // Notice that the cast can now be eliminated.
            if(first.CompareTo(value.Second.Item) < 0) {
                // …   // first is less than second.
            }
            else {
                //...    // second is less than or equal to first.
            }
            _SubItems = value;
        }
    }
    private Pair<BinaryTree<T>> _SubItems;
}

2.11 类类型约束

        有时可能要求将类型实参转换为特定的类类型,这是通过类类型做到的。 例如:

public class EntityDictionary<TKey, TValue>
    : System.Collections.Generic.Dictionary<TKey, TValue>
where TValue : EntityBase
{ 
    //...
}
public class EntityBase
{}

        如果同时指定了多个约束,那么类类型约束必须第一个出现。同一个参数的多个类类型约束是不被允许的。类似的, 类类型约束不能指定密封类或者不是类的类型。

2.12 struct/class 约束

        另一个重要的约束是将类型参数限制为任何非可空的值类型或者任何引用类型 。 编译器不允许在约束中将System.ValueType指定为基类。但是C# 提供了关键字struct/class指定参数类型是值类型还是引用类型。

public struct Nullable<T> :
    IFormattable, IComparable,
    IComparable<Nullable<T>>, INullable
where T : struct
{
    // ...
}

        由于类类型约束要求指定特定的类哦, 所以类类型和struct/class 约束一起使用会相互矛盾, 因此,struct/class 约束和类类型约束不能一起使用。

        struct约束有个特别的地方, 可空值类型不符合此约束,应为可空值类型是从Nullable<T>派生的,后者已经对T应用了struct 约束。

2.13 多个约束

        对于任何给定的类型参数,都可以指定任意数量的接口约束,但是类类型约束只能是一个。每个约束都在一个以逗号分隔的列表中声明,每个参数类型前都需要使用where关键字。

public class EntityDictionary<TKey, TValue>
    : Dictionary<TKey, TValue>
    where TKey : IComparable<TKey>, IFormattable
    where TValue : EntityBase
    {
        // ...
    }

2.14 构造器约束

        某些情况下,需要在泛型类中创建类型实参的实例。但是并非所有的对象都保证有公共默认构造器,所以编译器不允许为未约束的类型调用默认构造器。

        为了克服这一限制,类在指定了其他约束后使用new().这就是所谓的构造器约束。 它要求实参类型必须有默认构造器。只能对默认构造器约束,不能为带参数的构造器指定约束。

public class EntityBase<TKey>
{
    public TKey Key { get; set; }
}
public class EntityDictionary<TKey, TValue> :
    Dictionary<TKey, TValue>
    where TKey : IComparable<TKey>, IFormattable
    where TValue : EntityBase<TKey>, new()
{
    // ...
    public TValue MakeValue(TKey key)
    {
        TValue newEntity = new TValue();
        newEntity.Key = key;
        Add(newEntity.Key, newEntity);
        return newEntity;
    }
    // ...
}

2.15 约束继承

        无论是泛型类型参数还是它们的约束,都不会被派生类继承,因为泛型类型参数不是成员。

        由于派生的泛型类型参数现在是泛型基类的类型实参,所以类型参数必须具有与基类相同(或更强)的约束。

class EntityBase<T> where T : IComparable<T>
{
    // ...
}

// ERROR: 
// The type 'T' must be convertible to 'System.IComparable<T>' 
// to use it as parameter 'T' in the generic type or 
// method. 
// class Entity<T> : EntityBase<T>
// {
//     ...
// }

2.16 约束限制

约束的限制:    

  • 不能合并使用类类型约束和struct/class 约束。
  • 不能限制从一些特殊类继承。 例如  object、 数组、 System.ValueType、 System.Enum、System.Delegate以及System.MulticastDelegate  
  • 不支持操作符约束 。           
  • 不支持用约束类型参数来限制类型必须实现特定的方法或操作符。只能通过类类型约束(限制方法和操作符)和接口约束(限制方法)来提供不完整支持。
public abstract class MathEx<T>
{
    public static T Add(T first, T second)
    {
        // Error: Operator '+' cannot be applied to 
        // operands of type 'T' and 'T'.
        // return first + second;
        return default(T);
    }
}
  • 不支持OR 条件 假如为一个类型参数提供多个接口约束,编译器认为不同约束之间总是存在一个AND关系。不能在约束之间指定OR关系。
public class BinaryTree<T>
    // Error: OR is not supported.
    //where T: System.IComparable<T> || System.IFormattable
{
    // ...
}
  • 委托和枚举类型的约束是无效的 委托类型,数组类型和枚举类型不能在基类中使用,因为他们实际是”密封”的。
// Error:  Constraint cannot be special class 'System.Delegate'
//public class Publisher<T>
//    where T : System.Delegate{
//    public event T Event;
//    public void Publish()
//    {
//        if(Event != null)
//                Event(this, new EventArgs());
//    }
//}
  • 构造器约束只针对默认构造器。 为了克服该限制,一个方法是提供一个工厂接口,让他包含一个方法对类型进行实例化,实现接口的工厂负责实例化实体。
public class EntityBase<TKey>
{
    public EntityBase(TKey key)
    {
        Key = key;
    }
    public TKey Key { get; set; }
}
public interface IEntityFactory<TKey, TValue>
{
    TValue CreateNew(TKey key);
}
public class EntityDictionary<TKey, TValue, TFactory> :
    Dictionary<TKey, TValue>
    where TKey : IComparable<TKey>, IFormattable
    where TValue : EntityBase<TKey>
    where TFactory : IEntityFactory<TKey, TValue>, new()
{
    public TValue New(TKey key)
    {
        TFactory factory = new TFactory();
        TValue newEntity = factory.CreateNew(key);
        Add(newEntity.Key, newEntity);
        return newEntity;
    }
    //...
} 
public class Order : EntityBase<Guid>
{
    public Order(Guid key) :
        base(key)
    {
            // ...
    }
}
public class OrderFactory : IEntityFactory<Guid, Order>
{
    public Order CreateNew(Guid key)
    {
        return new Order(key);
    }
}

2.17 泛型方法

        泛型方法要使用泛型类型参数,这一点和泛型类型一致。在泛型和非泛型类型中都可以使用泛型方法。 要使用泛型方法,要在方法名后添加类型参数,例如:

public static class MathEx
{
    public static T Max<T>(T first, params T[] values)
        where T : IComparable<T>
    {
        T maximum = first;
        foreach(T item in values)
        {
            if(item.CompareTo(maximum) > 0)
            {
                maximum = item;
            }
        }
        return maximum;
    }
    // ….. 
}

2.18 泛型方法类型推断

        调用泛型方法时,要在方法的类型名后提供类型实参, 例如:

public static void  Main()
{
    Console.WriteLine(
        MathEx.Max<int>(7, 490));
        //….
}

        在大多数情况下,可以在调用时不指定类型实参。这就是所谓的类型推断。方法类型推断算法在进行推断时,只考虑方法实参、实参类型以及形参类型。

2.20 约束的指定

        泛型方法的类型参数也允许指定约束,其方式与在泛型类型中指定类型参数方式相同,例如:

public class ConsoleTreeControl {
    public static void Show<T>(BinaryTree<T> tree, int indent)
        where T : IComparable<T>
   {
       Console.WriteLine("\n{0}{1}", "+ --".PadLeft(5 * indent, ' '), tree.Item.ToString());
       if(tree.SubItems.First != null)
            Show(tree.SubItems.First, indent + 1);
       if(tree.SubItems.Second != null)
           Show(tree.SubItems.Second, indent + 1);
    }
}

        由于BinaryTree<T> 为类型T施加了约束,而 Show<T> 使用了BinaryTree<T>, 所以Show<T> 需要施加约束。

2.21 泛型的实例化

        基于值类型的泛型实例化:用值类型作为类型参数首次构造一个泛型类型时,”运行时” 会将指定类型参数放到CIL的合适位置,从而创建一个具体化的泛型类型。总之,”运行时” 会针对每个新的” 参数值类型“ 创建一个新的具体化的泛型类型。

        基于引用类型的泛型实例化:使用引用类型作为类型参数首次构造一个泛型类型时,运行时会在CIL代码中用object 替换参数类型创建一个具体化的泛型类型(而不是基于所提供的类型参数创建一个具体化的泛型类型). 以后,每次用引用类型参数实例化一个构造好的类型,运行时都会重用以前生成好的泛型类型的版本。文章来源地址https://www.toymoban.com/news/detail-726411.html

到了这里,关于【C# Programming】异常处理、泛型的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C#异常和异常处理

    C# 语言的异常处理功能有助于处理在程序运行期间发生的任何意外或异常情况。 异常处理功能使用   try 、 catch  和  finally  来尝试执行可能失败的操作、在你确定合理的情况下处理故障,以及在事后清除资源。 公共语言运行时 (CLR)、.NET/第三方库或应用程序代码都可

    2024年02月11日
    浏览(33)
  • 每个.NET开发都应掌握C#泛型的知识点

    C#泛型编程是.NET framework 2.0的新特征,它提高了代码安全性和代码重用的问题。由于泛型必须指定类型,正确的使用可以避免了装箱拆箱的问题;使用了泛型后,可以将算法或组件泛型化,基于类型参数支持任意数据类型,从而提高了代码的重用性。 C#泛型编程在C#是很重要的特

    2024年02月15日
    浏览(37)
  • C# 异常处理机制和常见的异常类型

    在 C# 中,异常处理是一个非常重要的概念,它可以让我们在程序发生错误时进行有效的处理,使程序具备更好的鲁棒性。C# 异常处理机制基于 try-catch-finally 语句块,其基本用法如下: 在上面的代码中,try 块中的代码可能会抛出一些异常,如果发生异常,则会进入到相应的

    2023年04月21日
    浏览(24)
  • 【C#】IIS平台下,WebAPI发布及异常处理

    目录 前言 一、技术介绍 1.1 IIS概念 1.2 WebApi概念 二、部署准备 2.1 Visual Studio本地项目配置 2.2 运行调试,以本地 localhost(或127.0.0.1)形式访问 2.3 运行调试,以本地IP(192.168.6.152)形式访问 三、详细步骤 3.1 打包发布 3.2 安装IIS(Internet信息服务) 3.3 配置IIS(Internet信息服务

    2023年04月20日
    浏览(34)
  • unity的C#学习——预处理指令、异常处理和文件的输入输出

    C# 中的预处理器指令是用来 指示编译器在 编译代码之前 执行一些预处理操作 的特殊指令。预处理器指令以 井号 # 开始,并且必须出现在代码的最外层,不能包含在方法或类的内部。 #define 指令用于定义一个符号常量。符号常量可以在代码中使用 #if 或 #elif 指令进行条件编

    2024年03月22日
    浏览(27)
  • 配置legacyUnhandledExceptionPolicy属性防止处理异常后程序崩溃退出(C#)

    这是这篇文章后面遗留的问题: winform中的全局异常信息_winform全局异常捕获_zxy2847225301的博客-CSDN博客 就是线程抛出异常后,被AppDomain.CurrentDomain.UnhandledException注册的事件捕获后,程序依旧崩溃退出。 解决方案:在app.config配置文件中的runtime节点中加上legacyUnhandledExceptionPol

    2024年02月09日
    浏览(32)
  • Go语言入门10(异常处理)

    ​如果出现了panic异常,那么会停止当前函数的运行,然后会找recover()方法,如果没有的话,就会报错退出程序,如果有就会执行recover的方法体中的方法 ​我们可以使用defer延迟处理函数来捕获panic异常,用recover()来从错误场景中恢复,必须的在defer修饰的方法中使用,不然不

    2023年04月23日
    浏览(33)
  • Java语言----异常处理(看了必会)

    目录 一.异常的概述 二.异常类的层次结构和种类 二.异常的基本用法 2.1异常的捕捉 2.2异常处理代码实现 三.抛出异常 3.1 throw 3.2 throws 四.finally的进一步详解 五.自定义异常类 总结 😽个人主页:tq02的博客_CSDN博客-C语言,Java领域博主  🌈理想目标:努力学习,向Java进发,拼搏

    2023年04月11日
    浏览(52)
  • 【C# Programming】C#第一课(自己学习的笔记)

    目录 一、C# 介绍 1.1 托管代码(Manage Code ) : 1.2 基础类型库 (Base Class Library): 1.3 程序集(Assembly): 1.4 .NET 框架: 1.5 公共中间语言(Common Intermediate Language),简称 IL。 1.6 C#编译器将源代码编译成CIL,从而生成程序集。 1.7 公共语言运行时 (Common Language Runtime ),简称 CLR。 1.8 所

    2024年02月12日
    浏览(29)
  • 【C# Programming】值类型、良构类型

    1、值类型         值类型的变量直接包含值。换言之, 变量引用的位置就是值内存中实际存储的位置。 2、引用类型         引用类型的变量存储的是对一个对象实例的引用(通常为内存地址)。         复制引用类型的值时,复制的只是引用。这个引用非常小(

    2024年02月07日
    浏览(27)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包