在C#中,implicit operatorexplicit operator 都用于用户定义的类型转换,但它们在转换方式和安全性上有重要区别。

1. implicit operator(隐式转换)

特点:

  • 自动进行,不需要显式类型转换
  • 转换是安全的,不会丢失数据或引发异常
  • 编译器自动识别并执行转换

示例代码:

public class Celsius
{
    public double Temperature { get; set; }
    
    public Celsius(double temp)
    {
        Temperature = temp;
    }
    
    // 隐式转换:double → Celsius
    public static implicit operator Celsius(double d)
    {
        return new Celsius(d);
    }
    
    // 隐式转换:Celsius → double
    public static implicit operator double(Celsius c)
    {
        return c.Temperature;
    }
}

// 使用示例
class Program
{
    static void Main()
    {
        // 隐式转换 - 自动进行
        Celsius c = 25.5;           // double 自动转为 Celsius
        double temp = c;            // Celsius 自动转为 double
        
        Console.WriteLine($"温度: {temp}°C"); // 输出: 温度: 25.5°C
        
        // 在方法调用中也自动转换
        DisplayTemperature(30.0);   // double 自动转为 Celsius
    }
    
    static void DisplayTemperature(Celsius celsius)
    {
        Console.WriteLine($"显示温度: {celsius.Temperature}°C");
    }
}

2. explicit operator(显式转换)

特点:

  • 必须显式指定类型转换
  • 可能丢失数据或引发异常
  • 需要程序员明确意图

示例代码:

public class Money
{
    public decimal Amount { get; set; }
    public string Currency { get; set; }
    
    public Money(decimal amount, string currency)
    {
        Amount = amount;
        Currency = currency;
    }
    
    // 显式转换:Money → decimal(可能丢失货币信息)
    public static explicit operator decimal(Money money)
    {
        return money.Amount;
    }
    
    // 显式转换:decimal → Money(需要指定默认货币)
    public static explicit operator Money(decimal amount)
    {
        return new Money(amount, "USD");
    }
}

// 使用示例
class Program
{
    static void Main()
    {
        Money salary = new Money(5000.00m, "USD");
        
        // 显式转换 - 必须明确指定
        decimal amount = (decimal)salary;        // Money → decimal
        Money money = (Money)2500.00m;           // decimal → Money
        
        Console.WriteLine($"金额: {amount}");    // 输出: 金额: 5000.00
        Console.WriteLine($"货币: {money.Currency}, 金额: {money.Amount}");
        
        // 如果不使用显式转换,编译器会报错
        // decimal wrong = salary; // 错误: 无法隐式转换
    }
}

3. 综合对比示例

public class Distance
{
    public double Meters { get; set; }
    
    public Distance(double meters)
    {
        Meters = meters;
    }
    
    // 隐式转换:int → Distance(总是安全的)
    public static implicit operator Distance(int meters)
    {
        return new Distance(meters);
    }
    
    // 显式转换:Distance → int(可能丢失精度)
    public static explicit operator int(Distance d)
    {
        return (int)d.Meters;
    }
    
    // 隐式转换:double → Distance(总是安全的)
    public static implicit operator Distance(double meters)
    {
        return new Distance(meters);
    }
    
    // 显式转换:Distance → double(安全,但为了对称性使用显式)
    public static explicit operator double(Distance d)
    {
        return d.Meters;
    }
    
    public override string ToString()
    {
        return $"{Meters}米";
    }
}

class Program
{
    static void Main()
    {
        // 隐式转换示例
        Distance d1 = 100;          // int → Distance (隐式)
        Distance d2 = 123.45;       // double → Distance (隐式)
        
        Console.WriteLine($"d1: {d1}"); // 输出: d1: 100米
        Console.WriteLine($"d2: {d2}"); // 输出: d2: 123.45米
        
        // 显式转换示例
        int metersInt = (int)d2;    // Distance → int (显式,丢失精度)
        double metersDouble = (double)d2; // Distance → double (显式)
        
        Console.WriteLine($"整数米数: {metersInt}");   // 输出: 整数米数: 123
        Console.WriteLine($"精确米数: {metersDouble}"); // 输出: 精确米数: 123.45
        
        // 在运算中的使用
        Distance total = d1 + 50;   // 隐式转换 50 → Distance
        Console.WriteLine($"总距离: {total}"); // 输出: 总距离: 150米
    }
}

4. 关键区别总结

特性implicit operatorexplicit operator
转换方式自动必须显式指定
安全性安全,不会丢失数据可能不安全,可能丢失数据
使用场景无损转换、小范围到大范围有损转换、大范围到小范围
编译器行为自动识别转换需要强制类型转换语法
代码可读性更简洁更明确意图

5. 最佳实践建议

  1. 使用 implicit operator 当:

    • 转换100%安全
    • 不会丢失信息
    • 转换是直观的
  2. 使用 explicit operator 当:

    • 可能丢失数据或精度
    • 转换可能失败
    • 需要用户明确转换意图
  3. 避免过度使用隐式转换,以免降低代码可读性。

这种机制让C#能够提供灵活的类型转换,同时保持类型安全性和代码清晰度。

原因在于每个扇区的物理字节数。

使用以下命令可以查看:

fsutil fsinfo sectorinfo c:
LogicalBytesPerSector :                                 512
PhysicalBytesPerSectorForAtomicity :                    32768
PhysicalBytesPerSectorForPerformance :                  32768
FileSystemEffectivePhysicalBytesPerSectorForAtomicity : 4096
设备校准 :                                        已校准(0x000)
设备上的分区校准:                                  已校准(0x000)
无搜寻惩罚
支持剪裁
不支持 DAX
未精简预配

这两个32768是导致sqlserver出错的原因。
解决方案就是执行以下命令:

reg add "HKLM\SYSTEM\CurrentControlSet\Services\stornvme\Parameters\Device" /v "ForcedPhysicalSectorSizeInBytes" /t reg_multi_sz /d "* 4095" /f

重启之后再查看结果:

LogicalBytesPerSector :                                 512
PhysicalBytesPerSectorForAtomicity :                    4096
PhysicalBytesPerSectorForPerformance :                  4096
FileSystemEffectivePhysicalBytesPerSectorForAtomicity : 4096
设备校准 :                                        已校准(0x000)
设备上的分区校准:                                  已校准(0x000)
无搜寻惩罚
支持剪裁
不支持 DAX
未精简预配

详情

取消默认可查看任何数据库

DENY VIEW any DATABASE TO PUBLIC;

赋予自己拥有管理权限的数据库的查看权限

ALTER AUTHORIZATION ON DATABASE::[Database] TO [User];

注意:
如果数据库已存在用户权限,则可能要删除后再操作

  • 一般的ID、Name:

    new TableDaoRelationship(nameof(PayOrder.User), UserDAO.Instance.TableName)
  • 一般的ID、Name、Value:

    new TableDaoRelationship(nameof(PayOrder.Merchant), MerchantDAO.Instance.TableName).SetOtherFiledsAsIdNameValue(nameof(Merchant.Name), nameof(Merchant.MchId))
  • 一般的ID、Value:

    new TableDaoRelationship(nameof(PayOrder.ProfitSharingPlanOrder), ProfitSharingPlanOrderDAO.Instance.TableName).SetOtherFiledsAsIdValue(nameof(ProfitSharingPlanOrder.Status))
  • 主表ID和关联表ID
    重点在于:SetSelfFieldAlias

    new TableDaoRelationship(nameof(PayOrder.ID), PayOrderTransactionDAO.Instance.TableName).SetSelfFieldAlias(nameof(PayOrder.Transaction)).SetOtherFileds(typeof(PayOrderTransactionInfo))
  • 指定关联表别名
    一般用于查询时需要使用关联表栏位作为查询条件
    重点在于:SetOtherTableAlias,使用时在生成查询条件时要指定Field。

    new TableDaoRelationship(nameof(PayOrder.ID), PayOrderTransactionDAO.Instance.TableName).SetSelfFieldAlias(nameof(PayOrder.Transaction)).SetOtherTableAlias(nameof(SQMIS.Model.PayOrderTransaction)).SetOtherFileds(typeof(PayOrderTransactionInfo))
    .AppendEqual(new Field(nameof(SQMIS.Model.PayOrderTransaction), nameof(SQMIS.Model.PayOrderTransaction.TransactionId)), this.TransactionID)
  • 多重关联时使用SetMoreLogicExpressions,可使用self和other来代替两个表的别名:

    new TableDaoRelationship(nameof(User.Principal), "RBAC_UserPrincipal").SetOtherFiledsAsIdNameValue("Name", "OuterID").SetMoreLogicExpressions(LogicExpression.BuildEqual(new Field("self", "Type"), new Field("other", "Type")))

计算机配置->管理模板->网络->Lanman 工作站->双击右边的”启用不安全的来宾登录“,然后点击“已启用”