.net 是否可以使用基于属性而不是类型的泛型约束?[duplicate]

lztngnrs  于 2022-12-27  发布在  .NET
关注(0)|答案(4)|浏览(136)
    • 此问题在此处已有答案**:

Can you use "where" to require an attribute in c#?(5个答案)
九年前就关门了。
我试图写一个类,将负责持久化应用程序选项。因为选项需要持久化,我发送的值必须是可序列化的。
最初我认为我已经能够编写一个带有如下签名的方法:

Public Sub SaveOption(Of T As ISerializable)(ByVal id As String, ByVal value As T)

或者如果您更喜欢C#:

public void SaveOption<T>(string id, T value) where T : ISerializable

原则上这是可以的,但是对于具有<Serializable>属性的类型呢?最值得注意的例子是System.String,它没有实现ISerializable,但是显然它是一个我应该能够保存的类型。
那么,有没有一种方法可以在编译时根据属性来限制哪些类型被允许进入一个方法?

wvt8vs2t

wvt8vs2t1#

对于其他类型,您可能有重载-以字符串为例:

public void SaveOption(string id, string value)

然而;可序列化性是...棘手的;我希望你在运行时检查一下。

webghufk

webghufk2#

属性约束不会实现太多,因为属性通常在编译时不提供任何保证,它们是运行时的信息,而不是编译器的信息。
在序列化的情况下,[Serializable]属性只是一个指示符,表明您可以在运行时 * 尝试 * 序列化,而ISerializable保证您可以序列化它,因为您可以明确地调用GetObjectData,而类的问题是确保它执行正确的操作。
例如,我可以

[Serializable]
class GoodClass
{
    public object Property { get; set; }
}

class BadClass
{
}

但是GoodClass并不比BadClass好,因为我可以

MemoryStream ms = new MemoryStream();
BinaryFormatter f = new BinaryFormatter();

GoodClass obj = new GoodClass();
f.Serialize(ms, obj); // OK

obj.Property = new BadClass();
f.Serialize(ms, obj); // BOOM

**EDIT:**属性也不会被继承,所以编译器不能确定在运行时传递的对象是否仍然具有您要求的属性:

class NotSoGoodClass : GoodClass // No [Serializable] attribute
{
}

...

SaveOption<GoodClass>( "id", new NotSoGoodClass() ) // oops
um6iljoc

um6iljoc3#

没有。:(
啊,不,实际上在C#4.0中他们引入了代码契约,这在这里应该是可行的。
此链接中的示例:CLR 4.0: Code Contracts

public void BuyMoreStuff(Item[] cart, ref Decimal totalCost, Item i)
{       
    CodeContract.Requires(totalCost >=0);
    CodeContract.Requires(cart != null);
    CodeContract.Requires(CodeContract.ForAll(cart, s => s != i));

    CodeContract.Ensures(CodeContract.Exists(cart, s => s == i);
    CodeContract.Ensures(totalCost >= CodeContract.OldValue(totalCost));
    CodeContract.EnsuresOnThrow<IOException>(totalCost == CodeContract.OldValue(totalCost));

    // Do some stuff
    …
}
jtjikinw

jtjikinw4#

检查这个是可能的,但你是对的,它必须在运行时完成,但比抛出一个异常更正式。

public static byte[] SerializeObject<T>(this T obj)
{
    Contract.Requires(typeof(T).IsSerializable);
    ...
}

相关问题